Granska SELECT-instruktionen
Transact-SQL eller T-SQL är en dialekt av DET ANSI-standardspråk för SQL som används av Microsoft SQL-produkter och -tjänster. Det liknar standard-SQL. Det mesta av vårt fokus kommer att ligga på SELECT-instruktionen, som har överlägset flest alternativ och varianter av en DML-instruktion.
Vi börjar med att titta på hur en SELECT-instruktion bearbetas på hög nivå. Ordningen i vilken en SELECT-instruktion skrivs är inte den ordning i vilken den utvärderas och bearbetas av SQL Server-databasmotorn.
Överväg följande fråga:
SELECT OrderDate, COUNT(OrderID) AS Orders
FROM Sales.SalesOrder
WHERE Status = 'Shipped'
GROUP BY OrderDate
HAVING COUNT(OrderID) > 1
ORDER BY OrderDate DESC;
Frågan består av en SELECT-instruktion som består av flera satser, som var och en definierar en specifik åtgärd som måste tillämpas på de data som hämtas. Innan vi undersöker körningens ordningsföljd för operationer ska vi kort ta en titt på vad den här frågan gör, även om detaljerna för de olika klausulerna inte kommer att omfattas i den här modulen.
SELECT-satsen returnerar kolumnen OrderDate och antalet OrderID-värden, som tilldelas namnet (eller aliaset) Orders:
SELECT OrderDate, COUNT(OrderID) AS Orders
FROM-satsen identifierar vilken tabell som är källan till raderna för frågan. I det här fallet är det tabellen Sales.SalesOrder :
FROM Sales.SalesOrder
WHERE-satsen filtrerar bort rader från resultaten och behåller endast de rader som uppfyller det angivna villkoret. i det här fallet beställningar som har statusen "levererad":
WHERE Status = 'Shipped'
GROUP BY-satsen tar de rader som uppfyllde filtervillkoret och grupperar dem efter OrderDate, så att alla rader med samma OrderDate betraktas som en enda grupp och en rad returneras för varje grupp:
GROUP BY OrderDate
När grupperna har skapats filtrerar HAVING-satsen grupperna baserat på dess egna predikat. Endast datum med mer än en beställning inkluderas i resultatet:
HAVING COUNT(OrderID) > 1
För att förhandsgranska fråga är den sista satsen ORDER BY, som sorterar utdata i fallande ordning av OrderDate:
ORDER BY OrderDate DESC;
Nu när du har sett vad varje sats gör ska vi titta på i vilken ordning SQL Server faktiskt utvärderar dem:
- FROM-satsen utvärderas först för att tillhandahålla källraderna för resten av satsen. En virtuell tabell skapas och skickas till nästa steg.
- WHERE-satsen ska utvärderas härnäst för att filtrera de rader i källtabellen som matchar ett predikat. Den filtrerade virtuella tabellen skickas till nästa steg.
- GROUP BY är nästa steg och ordnar raderna i den virtuella tabellen enligt unika värden som finns i LISTAN GROUP BY. En ny virtuell tabell skapas som innehåller listan över grupper och skickas till nästa steg. Från och med nu i åtgärdsflödet kan endast kolumner i GROUP BY-listan eller aggregerade funktioner refereras till av andra element.
- HAVING-satsen utvärderas härnäst och filtrerar bort hela grupper baserat på dess predikat. Den virtuella tabell som skapades i steg 3 filtreras och skickas till nästa steg.
- SELECT-satsen körs slutligen och avgör vilka kolumner som ska visas i frågeresultatet. Eftersom SELECT-satsen utvärderas efter de andra stegen kan inga kolumnalias (i vårt exempel Beställningar) som skapats där användas i GROUP BY- eller HAVING-satsen.
- ORDER BY-satsen är den sista som ska köras och sorterar raderna enligt kolumnlistan.
Här är den logiska ordningen vid körningen av SELECT-instruktionen ovan för att tillämpa den här förståelsen på vår exempelfråga:
FROM Sales.SalesOrder
WHERE Status = 'Shipped'
GROUP BY OrderDate
HAVING COUNT(OrderID) > 1
SELECT OrderDate, COUNT(OrderID) AS Orders
ORDER BY OrderDate DESC;
Alla möjliga satser krävs inte i varje SELECT-instruktion som du skriver. Den enda obligatoriska satsen är SELECT-satsen, som i vissa fall kan användas på egen hand. Vanligtvis ingår även en FROM-sats för att identifiera tabellen som efterfrågas. Dessutom har Transact-SQL andra satser som kan läggas till.
Som du har sett skriver du inte T-SQL-frågor i samma ordning som de utvärderas logiskt. Körningsordningen för utvärderingen avgör vilka data som är tillgängliga för vilka satser, eftersom en sats endast har åtkomst till information som redan gjorts tillgänglig från en redan bearbetad sats. Därför är det viktigt att förstå den sanna logiska bearbetningsordningen när du skriver frågor.
Markera alla kolumner
SELECT-satsen kallas ofta SELECT-listan eftersom den visar de värden som ska returneras i frågans resultat.
Den enklaste formen av en SELECT-sats är användningen av asterisktecknet (*) för att returnera alla kolumner. När den används i T-SQL-frågor kallas den för en stjärna. Även om SELECT * är lämpligt för ett snabbtest bör du undvika att använda det i produktionsarbetet av följande skäl:
- Ändringar i tabellen som lägger till eller ordnar om kolumner återspeglas i frågeresultatet, vilket kan resultera i oväntade utdata för program eller rapporter som använder frågan.
- Att returnera data som inte behövs kan göra dina frågor långsammare och orsaka prestandaproblem om källtabellen innehåller ett stort antal rader.
I följande exempel hämtas till exempel alla kolumner från tabellen (hypotetisk) Production.Product .
SELECT * FROM Production.Product;
Resultatet från den här frågan är en raduppsättning som innehåller alla kolumner för alla rader i tabellen, som kan se ut ungefär så här:
ProductID
Name
ProduktNummer
Färg
Standardkostnad
Listpris
Storlek
Vikt
ProductCatID
680
HL-ram för vägcykel – svart, 58
FR-R92B-58
Svart
1059.31
1431.5
58
1016.04
18
706
HL Road Frame – röd, 58
FR-R92R-58
Röd
1059.31
1431.5
58
1016.04
18
707
Sport – 100-hjälm, röd
HL-U509-R
Röd
13.0863
34.99
35
708
Sport-100-hjälm, svart
HL-U509
Svart
13.0863
34.99
35
...
...
...
...
...
...
...
...
...
Välja specifika kolumner
Med en explicit kolumnlista kan du ha kontroll över exakt vilka kolumner som returneras och i vilken ordning. Varje kolumn i resultatet har namnet på kolumnen som rubrik.
Tänk till exempel på följande fråga; som återigen använder den hypotetiska tabellen Production.Product .
SELECT ProductID, Name, ListPrice, StandardCost
FROM Production.Product;
Den här gången innehåller resultaten endast de angivna kolumnerna:
ProductID
Name
Listpris
Standardkostnad
680
HL-ram för vägcykel – svart, 58
1431.5
1059.31
706
HL Road Frame – röd, 58
1431.5
1059.31
707
Sport – 100-hjälm, röd
34.99
13.0863
708
Sport-100-hjälm, svart
34.99
13.0863
...
...
...
...
Välja uttryck
Förutom att hämta kolumner som lagras i den angivna tabellen kan en SELECT-sats utföra beräkningar och manipuleringar, som använder operatorer för att kombinera kolumner och värden eller flera kolumner. Resultatet av beräkningen eller manipulationen måste vara ett envärdesresultat (skalärt) som visas i resultatet som en separat kolumn.
Följande fråga innehåller till exempel två uttryck:
SELECT ProductID,
Name + '(' + ProductNumber + ')',
ListPrice - StandardCost
FROM Production.Product;
Resultatet från den här frågan kan se ut ungefär så här:
ProductID
680
HL Road Frame - Svart, 58 (FR-R92B-58)
372.19
706
HL Road Frame - Röd, 58 (FR-R92R-58)
372.19
707
Sport-100 Hjälm, Röd(HL-U509-R)
21.9037
708
Sport-100 Hjälm, Svart (HL-U509)
21.9037
...
...
...
Det finns några intressanta saker att notera om dessa resultat:
- Kolumnerna som returneras av de två uttrycken har inga kolumnnamn. Beroende på vilket verktyg du använder för att skicka frågan kan ett kolumnnamn som saknas indikeras av en tom kolumnrubrik, en literal indikator för "inget kolumnnamn" eller ett standardnamn som column1. Vi får se hur du anger ett alias för kolumnnamnet i frågan senare i det här avsnittet.
- Det första uttrycket använder operatorn + för att sammanfoga strängvärden (teckenbaserade) medan det andra uttrycket använder operatorn - för att subtrahera ett numeriskt värde från ett annat. När +-operatorn används med numeriska värden utför den addition. Det är därför viktigt att förstå datatyperna för de kolumner som du tar med i uttryck. Vi diskuterar datatyper i nästa avsnitt.
Ange kolumnalias
Du kan ange ett alias för varje kolumn som returneras av SELECT-frågan, antingen som ett alternativ till källkolumnnamnet eller för att tilldela ett namn till utdata från ett uttryck.
Här är till exempel samma fråga som tidigare, men med alias angivna för var och en av kolumnerna:
SELECT ProductID AS ID,
Name + '(' + ProductNumber + ')' AS ProductName,
ListPrice - StandardCost AS Markup
FROM Production.Product;
Resultatet från den här frågan innehåller de angivna kolumnnamnen:
ID
ProductName
Markup
680
HL Road Frame - Svart, 58 (FR-R92B-58)
372.19
706
HL Road Frame - Röd, 58 (FR-R92R-58)
372.19
707
Sport-100 Hjälm, Röd(HL-U509-R)
21.9037
708
Sport-100 Hjälm, Svart (HL-U509)
21.9037
...
...
...
Anteckning
AS-nyckelordet är valfritt när du anger ett alias, men det är bra att inkludera det för förtydligande.
Formatera frågor
Du kan notera i exemplen i det här avsnittet att du kan vara flexibel när det gäller hur du formaterar frågekoden. Du kan till exempel skriva varje sats (eller hela frågan) på en enda rad eller bryta den över flera rader. I de flesta databassystem är koden skiftlägesokänslig och vissa element i T-SQL-språket är valfria (inklusive AS-nyckelordet som nämnts tidigare och till och med semikolonet i slutet av en sats).
Överväg följande riktlinjer för att göra T-SQL-koden lättläst (och därför enklare att förstå och felsöka!):
- Ange versaler för T-SQL-nyckelord som SELECT, FROM, AS och så vidare. Versaler för nyckelord är en vanlig konvention som gör det lättare att hitta varje del av ett yttrande i ett komplext uttalande.
- Starta en ny rad för varje huvudsats i ett påstående.
- Om SELECT-listan innehåller fler än några kolumner, uttryck eller alias bör du överväga att visa varje kolumn på en egen rad.
- Dra in rader som innehåller underklisslar eller kolumner för att göra det tydligt vilken kod som tillhör varje huvudsats.