Prozkoumání příkazu SELECT
Transact-SQL nebo T-SQL je dialekt standardního jazyka SQL ANSI používaného produkty a službami Microsoft SQL. Podobá se standardnímu SQL. Většina z nás se zaměří na příkaz SELECT, který má zdaleka nejvíce možností a variant jakéhokoli příkazu DML.
Začněme tím, že se podíváme na to, jak se zpracovává příkaz SELECT. Pořadí zápisu příkazu SELECT není pořadí, ve kterém se vyhodnocuje a zpracovává databázovým strojem SQL Serveru.
Představte si následující dotaz:
SELECT OrderDate, COUNT(OrderID) AS Orders
FROM Sales.SalesOrder
WHERE Status = 'Shipped'
GROUP BY OrderDate
HAVING COUNT(OrderID) > 1
ORDER BY OrderDate DESC;
Dotaz se skládá z příkazu SELECT, který se skládá z více klauzulí, z nichž každá definuje konkrétní operaci, která se musí použít na načtená data. Než se podíváme na pořadí operací za běhu, pojďme se krátce podívat na to, co tento dotaz dělá, i když podrobnosti různých klauzulí se v tomto modulu nezabírají.
Klauzule SELECT vrátí sloupec OrderDate a počet hodnot OrderID , kterým se přiřadí název (nebo alias) Orders:
SELECT OrderDate, COUNT(OrderID) AS Orders
Klauzule FROM identifikuje, která tabulka je zdrojem řádků dotazu; v tomto případě se jedná o tabulku Sales.SalesOrder :
FROM Sales.SalesOrder
Klauzule WHERE filtruje řádky z výsledků a zachovává pouze ty řádky, které splňují zadanou podmínku; v tomto případě objednávky se stavem "odesláno":
WHERE Status = 'Shipped'
Klauzule GROUP BY přebírá řádky, které splňovaly podmínku filtru, a seskupuje je podle OrderDate, takže všechny řádky se stejným názvem OrderDate se považují za jednu skupinu a pro každou skupinu se vrátí jeden řádek:
GROUP BY OrderDate
Jakmile se skupiny vytvoří, klauzule HAVING filtruje skupiny na základě vlastního predikátu. Ve výsledcích budou zahrnuta pouze data s více než jednou objednávkou:
HAVING COUNT(OrderID) > 1
Pro účely náhledu tohoto dotazu je konečná klauzule ORDER BY, která seřadí výstup do sestupného pořadí orderDate:
ORDER BY OrderDate DESC;
Teď, když jste viděli, co jednotlivé klauzule dělá, se podíváme na pořadí, ve kterém je SQL Server skutečně vyhodnocuje:
- Nejprve se vyhodnocuje klauzule FROM, která poskytuje zdrojové řádky pro zbytek příkazu. Vytvoří se virtuální tabulka a předá se dalšímu kroku.
- Vedle vyhodnocení klauzule WHERE se vyfiltrují řádky ze zdrojové tabulky, které odpovídají predikátu. Filtrovaná virtuální tabulka se předá dalšímu kroku.
- GROUP BY je další, uspořádání řádků ve virtuální tabulce podle jedinečných hodnot nalezených v seznamu GROUP BY. Vytvoří se nová virtuální tabulka obsahující seznam skupin a předá se dalšímu kroku. Od tohoto okamžiku v toku operací mohou být odkazovány jinými prvky pouze sloupce v seznamu GROUP BY nebo agregační funkce.
- Klauzule HAVING se vyhodnocuje dále a vyfiltruje celé skupiny na základě jejího predikátu. Virtuální tabulka vytvořená v kroku 3 se vyfiltruje a předá dalšímu kroku.
- Klauzule SELECT se nakonec spustí a určí, které sloupce se zobrazí ve výsledcích dotazu. Vzhledem k tomu, že se klauzule SELECT vyhodnocuje po dalších krocích, nelze v klauzuli GROUP BY nebo HAVING použít všechny aliasy sloupců (v našem příkladu Objednávky).
- Klauzule ORDER BY je poslední, která se má provést a seřadí řádky podle seznamu sloupců.
Pokud chcete tento princip použít u našeho ukázkového dotazu, tady je logické pořadí za běhu výše uvedeného příkazu SELECT:
FROM Sales.SalesOrder
WHERE Status = 'Shipped'
GROUP BY OrderDate
HAVING COUNT(OrderID) > 1
SELECT OrderDate, COUNT(OrderID) AS Orders
ORDER BY OrderDate DESC;
Ne všechny možné klauzule jsou vyžadovány v každém příkazu SELECT, který napíšete. Jedinou povinnou klauzulí je klauzule SELECT, která se dá v některých případech použít samostatně. K identifikaci tabulky, na kterou se dotazuje, je obvykle zahrnuta klauzule FROM. Kromě toho transact-SQL obsahuje další klauzule, které lze přidat.
Jak jste viděli, nezapisujete dotazy T-SQL ve stejném pořadí, ve kterém jsou logicky vyhodnoceny. Pořadí běhu vyhodnocení určuje, jaká data jsou k dispozici pro které klauzule, protože klauzule má přístup pouze k informacím, které jsou již zpřístupněny z již zpracovávané klauzule. Z tohoto důvodu je důležité při psaní dotazů porozumět skutečnému pořadí logického zpracování.
Výběr všech sloupců
Klauzule SELECT se často označuje jako seznam SELECT, protože obsahuje hodnoty, které se mají vrátit ve výsledcích dotazu.
Nejjednodušší formou klauzule SELECT je použití znaku hvězdičky (*) k vrácení všech sloupců. Při použití v dotazech T-SQL se nazývá hvězdička. I když je select * vhodný pro rychlý test, měli byste se vyhnout jeho použití v produkční práci z následujících důvodů:
- Změny v tabulce, která přidává nebo mění uspořádání sloupců, se projeví ve výsledcích dotazu, což může vést k neočekávanému výstupu pro aplikace nebo sestavy, které dotaz používají.
- Vrácení dat, která nejsou potřebná, může zpomalit vaše dotazy a způsobit problémy s výkonem, pokud zdrojová tabulka obsahuje velký počet řádků.
Například následující příklad načte všechny sloupce z tabulky Production.Product (hypotetické).
SELECT * FROM Production.Product;
Výsledkem tohoto dotazu je sada řádků, která obsahuje všechny sloupce pro všechny řádky tabulky, což může vypadat nějak takto:
ProductID
Název
ProductNum
Color
StandardCost
ListPrice
Velikost
Hmotnost
ProductCatID
680
HL Road Frame - Black, 58
FR-R92B-58
Černá
1059.31
1431.5
58
1016.04
18
706
HL Road Frame - Red, 58
FR-R92R-58
Červený
1059.31
1431.5
58
1016.04
18
707
Sport-100 Helmet, Red
HL-U509-R
Červený
13.0863
34.99
35
708
Přilba Sport-100, černá
HL-U509
Černá
13.0863
34.99
35
...
...
...
...
...
...
...
...
...
Výběr konkrétních sloupců
Explicitní seznam sloupců umožňuje mít kontrolu nad přesně tím, které sloupce se vrátí a v jakém pořadí. Každý sloupec ve výsledku bude mít název sloupce jako záhlaví.
Představte si například následující dotaz; která znovu používá hypotetickou tabulku Production.Product .
SELECT ProductID, Name, ListPrice, StandardCost
FROM Production.Product;
Tentokrát výsledky zahrnují pouze zadané sloupce:
ProductID
Název
ListPrice
StandardCost
680
HL Road Frame - Black, 58
1431.5
1059.31
706
HL Road Frame - Red, 58
1431.5
1059.31
707
Sport-100 Helmet, Red
34.99
13.0863
708
Přilba Sport-100, černá
34.99
13.0863
...
...
...
...
Výběr výrazů
Kromě načítání sloupců uložených v zadané tabulce může klauzule SELECT provádět výpočty a manipulace, které používají operátory ke kombinování sloupců a hodnot nebo více sloupců. Výsledkem výpočtu nebo manipulace musí být výsledek s jednou hodnotou (skalární), který se zobrazí ve výsledku jako samostatný sloupec.
Následující dotaz například obsahuje dva výrazy:
SELECT ProductID,
Name + '(' + ProductNumber + ')',
ListPrice - StandardCost
FROM Production.Product;
Výsledky z tohoto dotazu můžou vypadat nějak takto:
ProductID
680
HL Road Frame - černá, 58(FR-R92B-58)
372.19
706
HL Road Frame - červená, 58(FR-R92R-58)
372.19
707
Sport-100 Helma, Červená(HL-U509-R)
21.9037
708
Sport-100 Helma, Černá(HL-U509)
21.9037
...
...
...
K těmto výsledkům je potřeba poznamenat několik zajímavých věcí:
- Sloupce vrácené dvěma výrazy nemají žádné názvy sloupců. V závislosti na nástroji, který používáte k odeslání dotazu, může být chybějící název sloupce označený prázdným záhlavím sloupce, indikátorem literálu Bez názvu sloupce nebo výchozím názvem, jako je sloupec1. Dále v této části se dozvíme, jak zadat alias pro název sloupce v dotazu.
- První výraz používá + operátor ke zřetězení řetězcových hodnot (na základě znaků), zatímco druhý výraz používá - operátor k odečtení jedné číselné hodnoty od druhé. Při použití s číselnými hodnotami + operátor provede sčítání. Je zřejmé, že je důležité porozumět datovým typům sloupců, které do výrazů zahrnete. Datové typy probereme v další části.
Určení aliasů sloupců
Alias pro každý sloupec vrácený dotazem SELECT můžete zadat buď jako alternativu k názvu zdrojového sloupce, nebo přiřadit název výstupu výrazu.
Tady je například stejný dotaz jako předtím, ale s aliasy zadanými pro každý sloupec:
SELECT ProductID AS ID,
Name + '(' + ProductNumber + ')' AS ProductName,
ListPrice - StandardCost AS Markup
FROM Production.Product;
Výsledky tohoto dotazu zahrnují zadané názvy sloupců:
ID
ProductName
Značkování
680
HL Road Frame - černá, 58(FR-R92B-58)
372.19
706
HL Road Frame - červená, 58(FR-R92R-58)
372.19
707
Sport-100 Helma, Červená(HL-U509-R)
21.9037
708
Sport-100 Helma, Černá(HL-U509)
21.9037
...
...
...
Poznámka:
Klíčové slovo AS je volitelné při zadávání aliasu, ale je vhodné ho zahrnout k objasnění.
Formátování dotazů
Z příkladů v této části si můžete všimnout, že můžete být flexibilní o tom, jak formátujete kód dotazu. Můžete například napsat každou klauzuli (nebo celý dotaz) na jeden řádek nebo ji rozdělit na několik řádků. Ve většině databázových systémů kód nerozlišuje malá a velká písmena a některé prvky jazyka T-SQL jsou volitelné (včetně klíčového slova AS, jak jsme zmínili dříve, a dokonce i středníku na konci příkazu).
Zvažte následující pokyny, které usnadňují čitelnost kódu T-SQL (a proto je jednodušší pochopit a ladit!):
- Velká písmena klíčových slov T-SQL, jako je SELECT, FROM, AS atd. Velká písmena klíčových slov jsou běžně používané konvence, které usnadňují nalezení jednotlivých klauzulí komplexního příkazu.
- Spusťte nový řádek pro každou hlavní klauzuli příkazu.
- Pokud seznam SELECT obsahuje více než několik sloupců, výrazů nebo aliasů, zvažte výpis jednotlivých sloupců na vlastním řádku.
- Odsazení řádků obsahujících dílčí seznamy nebo sloupce, aby bylo jasné, který kód patří do každé hlavní klauzule.