Tento článek je prvním ze série o základech tabulkových výrazů v T-SQL. Zaměřím se především na čtyři typy pojmenovaných tabulkových výrazů, které jsou v T-SQL známé jako odvozené tabulky, běžné tabulkové výrazy (CTE), pohledy a inline tabulkové funkce (inline TVF).
K napsání této série mě inspiroval můj dobrý přítel Grant Fritchey, kterého znám mnoho let. Jak Grant opakovaně zdůrazňuje, mnoho lidí, kteří používají běžné tabulkové výrazy v T-SQL, si myslí, že SQL Server přetrvává vnitřní sadu výsledků dotazu a že důvodem tohoto přesvědčení je použití termínu tabulka v názvu konstrukce. Když se toto téma objeví v komunitních diskuzích, často lidé argumentují, že použití termínu tabulka v názvu konstruktu je nevhodné, protože to ve skutečnosti není tabulka. Existují dokonce návrhy na zahájení kampaně pojmenování v naději, že v budoucnu dojde ke změně názvu tohoto konstruktu, alespoň v T-SQL. Některé z návrhů zahrnují výraz dotazu , vložené zobrazení , zobrazení na úrovni příkazu , a další.
Možná to bude pro někoho překvapením, ale ve skutečnosti nacházím použití termínu tabulka v běžném tabulkovém výrazu jako velmi vhodné. Ve skutečnosti nacházím použití termínu tabulkový výraz podle potřeby. Pro mě je nejlepším způsobem, jak popsat, co je CTE v T-SQL, výraz pojmenované tabulky . Totéž platí pro to, co T-SQL nazývá odvozené tabulky (specifická jazyková konstrukce na rozdíl od obecné myšlenky), pohledy a inline TVF. Všechny jsou pojmenované tabulkové výrazy.
Pokud se mnou trochu vydržíte, zdůvodním svůj pohled na věc v tomto článku. Napadlo mě, že jak zmatek v pojmenování, tak zmatek kolem toho, zda výrazy v tabulkách obsahují aspekt persistence, lze odstranit lepším pochopením základů našeho oboru systémů správy relačních databází. Těmito základy jsou relační teorie, jak s ní souvisí SQL (standardní jazyk) a jak s obojím souvisí dialekt T-SQL používaný v implementacích SQL Server a Azure SQL Database.
Jako výchozí bod chcete být schopni odpovědět na následující otázky:
- Co znamená samostatnost fyzických dat princip v relačním modelu znamená?
- Co je tabulka v SQL a jaký je její protějšek v relačním modelu?
- Jaká je uzavírací vlastnost relační algebry?
- Co je tabulkový výraz a jaký je protějšek v relačním modelu?
Jakmile budete schopni správně odpovědět na výše uvedené otázky, velmi pravděpodobně narazíte na použití termínu výraz pojmenované tabulky jak je vhodné pro výše uvedené konstrukce (to, co T-SQL nazývá odvozené tabulky, CTE, pohledy a inline TVF).
Nechci, aby to znělo, jako bych velmi hluboce rozuměl teorii vztahů. Moje odbornost je T-SQL. Uznávám, že je toho mnohem víc, co o teorii vztahů nevím, než vím, a že některé věci, o kterých si myslím, že vím, tak prostě nejsou. Když čtu texty C. J. Datese na toto téma, mám pocit, že sotva poškrábu povrch toho, co se dá vědět, a že bych se mohl a měl snažit tomu lépe porozumět. Uznávám a pevně věřím, že dobré porozumění relační teorii se přímo promítá do lepšího porozumění SQL a T-SQL a do psaní lepšího, přesnějšího a robustnějšího kódu T-SQL. Každému, kdo si zvolil data jako svou kariéru, doporučuji přečíst si SQL and Relational Theory:How to Write Accurate SQL Code 3rd Edition od C. J. Date (O'Reilly 2015).
V první části této série chci pochopit, jak používám výrazy tabulkový výraz a výraz pojmenované tabulky , což je v souladu s tím, jak Date používá tento termín, a bohužel není v souladu s tím, jak tento termín používá standard SQL. Abych toho dosáhl, poskytnu trochu pozadí z relační teorie a standardu SQL. Ale jak jsem řekl, doporučuji přečíst si Date’s book pro skutečně podrobné pokrytí tohoto tématu.
Začnu vysvětlením, co znamená princip fyzické nezávislosti dat. Dále vysvětlím, co je tabulka v SQL a její protějšek v relační teorii. Poté vysvětlím, co znamená uzavírací vlastnost relační algebry. Jakmile máte rozumnou představu o tom, co je tabulka a co znamená vlastnost closure, bude docela jednoduché pochopit, co je tabulkový výraz. Poté se zaměřím na specifika v T-SQL. Mám hodně co říct o základech tabulkových výrazů v T-SQL – jak z hlediska koncepčního zpracování, tak z hlediska detailů implementace, včetně fyzické reprezentace a úvah o ladění dotazů.
Považuji toto téma za fascinující a velmi praktické, jakmile se ponoříte do podrobností implementace. Popravdě, mám k tomu tolik co říct, že si nejsem jistý, kolik dílů tato série nakonec bude obsahovat. Co vám mohu s velkou mírou jistoty říci, je, že bude mít více dílů. Pravděpodobně více než jeden a méně než 100. V dalších dílech se budu ponořit do jednotlivých typů pojmenovaných tabulkových výrazů, úvah o úpravách, vkládání aspektů, aspektů řazení, korelací a dalších.
Ve svých příkladech použiji ukázkovou databázi nazvanou TSQLV5. Skript, který vytváří a naplňuje tuto databázi, najdete zde a její ER diagram zde.
Fyzická nezávislost na datech
Fyzická nezávislost na datech je princip v relační teorii, který říká, že detaily fyzické implementace by měly být skryty nebo transparentní pro uživatele zasílajícího dotazy do systému správy relačních databází. V dotazech se uživatelé mají zaměřit na co potřebují používat logické operace, které jsou založeny na relační algebře, na rozdíl od jak získat data. Neměli by se starat o to, jak jsou data strukturována, zpřístupňována a zpracovávána. Takové fyzické detaily implementace mají tendenci se podstatně lišit mezi různými implementacemi (produkty RDBMS). I se stejným RDBMS se někdy detaily fyzické implementace mezi různými verzemi a sestaveními mění. Teoretickou myšlenkou principu nezávislosti fyzických dat je chránit uživatelské investice odstraněním potřeby revidovat svá řešení, když upgradujete RDBMS na novou verzi, nebo dokonce když migrujete z jednoho RDBMS na jiný. Jak asi dobře víte, v praxi věci nejsou tak jednoduché, ale to je téma na jinou diskusi.
Co je tabulka?
Pokud nějakou dobu pracujete s T-SQL nebo jakýmkoli jiným dialektem SQL, získáte intuitivní pochopení toho, co je tabulka. Problém je v tom, že bez určitého zázemí teorie vztahů není intuitivní porozumění často příliš přesné. Jednou z typických chyb je, že máme intuitivní tendenci soustředit se na detaily fyzické implementace. Když například přemýšlíte o tom, co je tabulka, uvažujete o tabulce jako o logické struktuře (souboru řádků) nebo o podrobnostech fyzické implementace na platformě, kterou používáte (na serveru SQL Server , stránky, rozsahy, halda versus seskupený index, neshlukované indexy a tak dále)? Jako uživatel, který píše kód SQL pro dotaz na tabulku, podle principu nezávislosti na fyzických datech, byste měli uvažovat o tabulce jako o logické struktuře a nechat RDBMS starat se o detaily fyzické implementace. Udělejme tedy krok zpět a zkusme zjistit, co je to stůl.
Tabulka je protějškem SQL k hlavní struktuře v relační teorii – relaci. Abychom věci zjednodušili a omezili rozsah mého pokrytí, nebudu se zabývat rozdílem mezi proměnnou vztahu a hodnotou vztahu. Pokud se budete řídit mým doporučením a přečtete si Date’s book, velmi rychle získáte jasnou představu o těchto jemnostech.
Vztah má nadpis a tělo.
Záhlaví vztahu je množina z atributů . V matematické teorii množin nemá množina pořadí a žádné duplikáty. Atribut byste měli identifikovat podle jména a ne podle nějaké pozice. Názvy atributů proto musí být jedinečné.
Dokážete určit, co je protějškem atributu v SQL? Pravděpodobně jste uhodli, že jde o sloupec . SQL však ve skutečnosti má představu o pořadí svých sloupců na základě jejich pořadí zobrazení v příkazu CREATE TABLE. Zde je například příkaz CREATE TABLE pro tabulku Sales.Shippers v databázi TSQLV5:
CREATE TABLE Sales.Shippers ( shipperid INT NOT NULL IDENTITY, companyname NVARCHAR(40) NOT NULL, phone NVARCHAR(24) NOT NULL, CONSTRAINT PK_Shippers PRIMARY KEY(shipperid) );
Dotazujte se na tabulku pomocí notoricky známého SELECT *
, asi takhle:
SELECT * FROM Sales.Shippers;
Když jsem spustil tento dotaz v mém systému, dostal jsem následující výstup:
shipperid companyname phone ---------- -------------- --------------- 1 Shipper GVSUA (503) 555-0137 2 Shipper ETYNR (425) 555-0136 3 Shipper ZHISN (415) 555-0138
SQL zaručuje, že sloupce budou vráceny zleva doprava na základě pořadí definic. Brzy vysvětlím, co se stane s řádky. SQL dokonce umožňuje odkazovat na řadovou pozici sloupce ze seznamu SELECT v klauzuli ORDER BY, jako je to tak (ne že bych tuto praxi nedoporučoval, ani Aaron Bertrand):
SELECT shipperid, companyname, phone FROM Sales.Shippers ORDER BY 2;
Tento dotaz generuje následující výstup:
shipperid companyname phone ---------- -------------- --------------- 2 Shipper ETYNR (425) 555-0136 1 Shipper GVSUA (503) 555-0137 3 Shipper ZHISN (415) 555-0138
Tělo vztahu je množina n-tic . Znovu připomeňme, že sada nemá žádné pořadí a žádné duplikáty. Relace proto musí mít alespoň jeden kandidátský klíč, který vám umožní jednoznačně identifikovat n-tici. Protějškem SQL k n-tici je řádek . V SQL však nejste nuceni definovat klíč v tabulce, a pokud tak neučiníte, můžete skončit s duplicitními řádky. I když máte v tabulce definován klíč, můžete získat duplicitní řádky vrácené z dotazu na tabulku. Zde je příklad:
SELECT country FROM HR.Employees;
Tento dotaz generuje následující výstup:
country -------- USA USA USA USA UK UK UK USA UK
Tento dotaz nevytváří relační výsledek kvůli možnosti duplicitních řádků. Zatímco relační teorie je založena na teorii množin, SQL je založena na teorii více množin. Multiset (neboli superset nebo taška) může mít duplikáty. SQL vám poskytuje nástroj k odstranění duplikátů s klauzulí DISTINCT, jako například:
SELECT DISTINCT country FROM HR.Employees;
Tento dotaz generuje následující výstup:
country -------- UK USA
To, co SQL zachovává z relační teorie, pokud jde o tělo tabulky, je vlastnost no-order. Pokud do dotazu nepřidáte klauzuli ORDER BY, nemáte žádné záruky, že výsledek bude mít mezi řádky nějaké konkrétní pořadí. Takže tělo výše uvedeného výsledku dotazu je relační, alespoň v tom smyslu, že nemá duplikáty a nemá zaručené pořadí.
Předpokládejme, že dotazujete tabulku na SQL Server a do dotazu nezahrnujete klauzuli ORDER BY. Očekáváte, že SQL Server vždy vrátí řádky v určitém konkrétním pořadí jako zaručené chování? Mnoho lidí ano. Mnozí si myslí, že vždy získáte řádky zpět na základě pořadí seskupeného indexu. To je dobrý příklad ignorování principu nezávislosti fyzických dat a vytváření předpokladů založených na intuici a možná na základě chování pozorovaného v minulosti. Microsoft ví, že dotaz SQL bez klauzule ORDER BY nezaručuje žádné pořadí mezi výslednými řádky, a proto i když na fyzické úrovni jsou data umístěna ve struktuře indexu, SQL Server nemusí zpracovávat data v indexu. objednat. Za určitých fyzických podmínek se může rozhodnout, že tak učiní, ale může se rozhodnout, že za jiných fyzických podmínek neučiní. Pamatujte také, že podrobnosti fyzické implementace se mohou mezi různými verzemi a sestaveními produktu měnit. Pokud chcete zaručit, že dotaz vrátí řádky výsledků v určitém konkrétním pořadí, jediným způsobem, jak to zaručit, je vložit do nejvzdálenějšího dotazu klauzuli ORDER BY.
Jak jste pravděpodobně zjistili, návrháři SQL ve skutečnosti nepovažovali za prioritu následovat relační teorii. A to, co jsem zde popsal, je jen několik příkladů. Je jich mnohem víc. Jak již bylo zmíněno dříve, mým cílem v tomto článku je pouze poskytnout dostatek kritického teoretického základu k odstranění zmatku kolem tabulkových výrazů, než se v budoucích článcích začnu ponořit do specifik T-SQL.
Co je tabulkový výraz?
Relační algebra (algebra, která definuje operace na relacích v teorii relací) má uzávěr vlastnictví. To znamená, že operace na relacích dává vztah. Relační operátor pracuje na jednom nebo více relacích jako na vstupu a dává jedinou relaci jako výstup. Vlastnost closure umožňuje vnořovat operace. relační výraz je výraz, který funguje na relacích a vrací relaci. Relační výraz lze tedy použít tam, kde relační algebra očekává relaci.
Pokud se nad tím zamyslíte, neliší se to od operací s celými čísly, které dávají celočíselný výsledek. Předpokládejme, že proměnná @i je celočíselná proměnná. Výraz @i + 42 dává celé číslo, a proto jej lze použít tam, kde se očekává celé číslo, jako v (@i + 42) * 2.
Vzhledem k tomu, že tabulka v SQL je protějškem relace v relační teorii, i když ne příliš úspěšným, je tabulkový výraz v SQL protějškem relačního výrazu. Jak již bylo zmíněno dříve, používám výraz tabulky po použití tohoto výrazu C. J. Datesem. Standard SQL obsahuje spoustu matoucích termínů, z nichž se obávám, že některé nejsou příliš vhodné. Například standard SQL používá výraz tabulkový výraz ke konkrétnímu popisu výrazu založeného na klauzuli dotazu začínající povinnou klauzulí FROM a volitelně včetně klauzulí WHERE, GROUP BY, HAVING a WINDOW (poslední není podporováno v T -SQL) a s výjimkou klauzule SELECT. Zde je specifikace standardu:
7.4
Funkce
Určete tabulku nebo seskupenou tabulku.
Formátovat
Je pravda, že výsledek toho, co standard nazývá tabulkový výraz, je považován za tabulku, ale takový výraz nemůžete použít jako samostatný dotaz. Datumová verze výrazu tabulky termínu je ve skutečnosti blíže tomu, co standard SQL nazývá výraz dotazu . Zde je specifikace standardu pro to, co nazývá výraz dotazu:
7.17
Funkce
Formátovat
7.3
Funkce
Formátovat
Všimněte si, že tato specifikace zahrnuje to, co T-SQL nazývá společným tabulkovým výrazem, i když standard tento výraz ve skutečnosti nepoužívá, spíše jej nazývá s prvkem seznamu . Všimněte si také, že takzvaný dotazový výraz nemusí být založen na dotazu, ale může být založen na tom, co se nazývá konstruktor hodnot tabulky (použití klauzule VALUES k vytvoření sady řádků). A konečně, i když je standardní výraz dotazu založen na výrazu, vrací tabulku a lze jej použít tam, kde se tabulka normálně očekává. Z těchto důvodů považuji Dateovo použití termínu tabulkový výraz za mnohem vhodnější.
Chápu, proč by se některým mohlo zdát zdržování se pojmenováním a terminologií trochu pedantské a možná dokonce ztrátou času. Cítím se však úplně jinak. Věřím, že v jakémkoli oboru vás touha používat vlastní jména a terminologii nutí dobře studovat základy a odráží se ve vašich znalostech. V naději, že se mi v tomto článku nepodařilo vás odcizit natolik, abyste nechtěli pokračovat k nadcházejícím dílům série, počínaje článkem příštího měsíce se zaměřím na způsob, jakým různé typy jmen tabulkové výrazy se na SQL Server a Azure SQL Database zpracovávají pomocí T-SQL.
[
[
[
[
Určete tabulku.
[ ]
[
::=
S [ REKURSIVNÍ ]
[ { <čárka> }… ]
::=
AS
|
[
|
[
|
[
|
[
|
|
TABLE
ODPOVÍDAJÍCÍ [ BY
ORDER BY
OFFSET
NAČÍST { FIRST | NEXT } [
|
Určete sadu
HODNOTY
HODNOTY
[ { <čárka> Závěr