Dit artikel is het eerste in een reeks over de basisprincipes van tabeluitdrukkingen in T-SQL. Ik zal me voornamelijk concentreren op vier soorten benoemde tabeluitdrukkingen, die in T-SQL bekend staan als afgeleide tabellen, algemene tabeluitdrukkingen (CTE's), views en inline tabelwaardefuncties (inline TVF's).
Ik werd geïnspireerd om deze serie te schrijven door mijn goede vriend, Grant Fritchey, die ik al vele jaren ken. Zoals Grant herhaaldelijk opmerkt, denken velen die algemene tabeluitdrukkingen in T-SQL gebruiken dat SQL Server de interne queryresultatenset aanhoudt, en dat de reden voor deze overtuiging het gebruik van de term tabel is. in de naam van de constructie. Wanneer dit onderwerp ter sprake komt in communitydiscussies, beweren mensen vaak dat het gebruik van de term tabel in de naam van de constructie ongepast is, omdat het niet echt een tabel is. Er zijn zelfs suggesties om een naamgevingscampagne te starten in de hoop een toekomstige naamsverandering voor dit construct te zien, althans in T-SQL. Sommige van de suggesties bevatten query-expressie , inline-weergave , weergave op instructieniveau , en anderen.
Misschien zal dit voor sommigen als een verrassing komen, maar ik vind het gebruik van de term tabel eigenlijk wel handig in gewone tabeluitdrukking als zeer geschikt. In feite vind ik het gebruik van de term tabeluitdrukking zoals gepast. Voor mij is de beste manier om te beschrijven wat een CTE is in T-SQL, een genoemde tabeluitdrukking . Hetzelfde geldt voor wat T-SQL afgeleide tabellen noemt (de specifieke taalconstructie in tegenstelling tot het algemene idee), views en inline TVF's. Het zijn allemaal benoemde tabeluitdrukkingen.
Als je me een beetje kunt verdragen, zal ik de redenering voor mijn kijk op de dingen in dit artikel geven. Het kwam bij me op dat zowel de naamsverwarring, als de verwarring over de vraag of er een persistentieaspect is aan tabeluitdrukkingen, kan worden opgelost met een beter begrip van de fundamenten van ons vakgebied van relationele databasebeheersystemen. Die fundamenten zijn, relationele theorie, hoe SQL (de standaardtaal) zich ermee verhoudt, en hoe het T-SQL-dialect dat wordt gebruikt in de SQL Server- en Azure SQL Database-implementaties zich tot beide verhoudt.
Om te beginnen wil je de volgende vragen kunnen beantwoorden:
- Wat betekent de onafhankelijkheid van fysieke gegevens principe in het relationele model betekent?
- Wat is een tabel in SQL en wat is de tegenhanger in het relationele model?
- Wat is de sluitingseigenschap van relationele algebra?
- Wat is een tabeluitdrukking en wat is de tegenhanger in het relationele model?
Zodra u de bovenstaande vragen correct kunt beantwoorden, zult u hoogstwaarschijnlijk het gebruik van de term benoemde tabeluitdrukking vinden. zoals gepast voor de bovengenoemde constructies (wat T-SQL afgeleide tabellen, CTE's, views en inline TVF's noemt).
Ik wil niet klinken alsof ik een heel diep begrip heb van relationele theorie. Mijn expertise is T-SQL. Ik erken dat er veel meer is dat ik niet weet over relationele theorie dan ik, en dat sommige dingen die ik denk te weten, gewoon niet zo zijn. Als ik de geschriften van C.J. Dates over dit onderwerp lees, heb ik het gevoel dat ik nog maar nauwelijks aan de oppervlakte kom van wat er te weten valt, en dat ik ernaar zou kunnen en moeten streven om het beter te begrijpen. Ik erken en ben er vast van overtuigd dat een goed begrip van de relationele theorie zich direct vertaalt in een beter begrip van SQL en T-SQL, en in het schrijven van betere, nauwkeurigere en robuustere T-SQL-code. Voor iedereen die data als carrière kiest, raad ik aan om SQL and Relational Theory:How to Write Accurate SQL Code 3rd Edition door C.J. Date (O'Reilly 2015) te lezen.
In het eerste deel van deze serie wil ik inzicht krijgen in mijn gebruik van de termen tabeluitdrukking en genoemde tabeluitdrukking , wat in overeenstemming is met het gebruik van deze term door Date, en helaas niet in overeenstemming met het gebruik van deze term door de SQL-standaard. Om dit te bereiken zal ik wat achtergrondinformatie geven uit de relationele theorie en de SQL-standaard. Maar zoals ik al zei, raad ik aan om het boek van Date te lezen voor een echt gedetailleerde beschrijving van dit onderwerp.
Ik zal beginnen met uit te leggen wat het principe van fysieke gegevensonafhankelijkheid inhoudt. Vervolgens zal ik uitleggen wat een tabel is in SQL en zijn tegenhanger in de relationele theorie. Ik zal dan uitleggen wat de sluitingseigenschap van relationele algebra betekent. Als je eenmaal een redelijk idee hebt van wat een tabel is, en wat de sluitingseigenschap betekent, wordt het vrij eenvoudig om te begrijpen wat een tabeluitdrukking is. Mijn focus zal dan gaan naar de details in T-SQL. Ik heb veel te zeggen over de basisprincipes van tabeluitdrukkingen in T-SQL, zowel in termen van de conceptuele behandeling als in termen van implementatiedetails, inclusief fysieke representatie en overwegingen bij het afstemmen van query's.
Ik vind dit onderwerp fascinerend en zeer praktisch als je je eenmaal verdiept in de implementatiedetails. Ik heb er zelfs zoveel over te zeggen dat ik niet zeker weet hoeveel delen deze serie uiteindelijk zal bevatten. Wat ik je met een grote mate van vertrouwen kan vertellen is dat er meerdere onderdelen zullen zijn. Waarschijnlijk meer dan één en minder dan 100. In toekomstige delen zal ik dieper ingaan op de afzonderlijke typen benoemde tabeluitdrukkingen, wijzigingsoverwegingen, inlining-aspecten, ordeningsaspecten, correlaties en meer.
In mijn voorbeelden gebruik ik een voorbeelddatabase met de naam TSQLV5. U vindt het script dat deze database maakt en vult hier, en het ER-diagram hier.
Fysieke gegevens onafhankelijkheid
Onafhankelijkheid van fysieke gegevens is een principe in de relationele theorie dat zegt dat de details van de fysieke implementatie verborgen moeten zijn voor, of transparant moeten zijn voor, de gebruiker die de query's indient tegen het relationele databasebeheersysteem. In de zoekopdrachten worden gebruikers verondersteld zich te concentreren op wat ze moeten logische bewerkingen gebruiken die gebaseerd zijn op relationele algebra, in tegenstelling tot hoe om de gegevens te verkrijgen. Ze hoeven zich geen zorgen te maken over hoe de gegevens zijn gestructureerd, toegankelijk en verwerkt. Dergelijke fysieke implementatiedetails hebben de neiging om aanzienlijk te verschillen tussen verschillende implementaties (RDBMS-producten). Zelfs met hetzelfde RDBMS veranderen de fysieke implementatiedetails soms tussen verschillende versies en builds. Het idee achter het principe van fysieke gegevensonafhankelijkheid is in theorie om de investering van de gebruiker te beschermen door de noodzaak weg te nemen om uw oplossingen te herzien wanneer u uw RDBMS naar een nieuwe versie upgradet, of zelfs wanneer u van het ene RDBMS naar het andere migreert. Zoals je waarschijnlijk goed weet, zijn de dingen in de praktijk niet zo eenvoudig, maar dat is een onderwerp voor een andere discussie.
Wat is een tafel?
Als je al een tijdje met T-SQL of een ander dialect van SQL werkt, ontwikkel je een intuïtief begrip van wat een tabel is. Het probleem is dat zonder enige achtergrond van relationele theorie, het intuïtieve begrip vaak niet erg nauwkeurig is. Een typische fout is dat we intuïtief de neiging hebben om ons te concentreren op fysieke implementatiedetails. Als u bijvoorbeeld nadenkt over wat een tabel is, denkt u dan aan een tabel als een logische structuur (een reeks rijen) of denkt u aan fysieke implementatiedetails in het platform dat u gebruikt (in SQL Server , pagina's, omvang, heap versus geclusterde index, niet-geclusterde indexen, enzovoort)? Als gebruiker die SQL-code schrijft om een tabel te doorzoeken, volgens het principe van fysieke gegevensonafhankelijkheid, wordt verondersteld dat u de tabel als een logische structuur beschouwt en het RDBMS zich zorgen maakt over de fysieke implementatiedetails. Laten we dus een stapje terug doen en proberen te achterhalen wat een tafel is.
Een tabel is de tegenhanger van SQL van de hoofdstructuur in de relationele theorie - een relatie. Om de zaken eenvoudig te houden en de reikwijdte van mijn dekking te beperken, ga ik niet in op het onderscheid tussen een relatievariabele en een relatiewaarde. Als je mijn aanbeveling opvolgt en het boek van Date leest, heb je heel snel een duidelijk beeld van dergelijke subtiliteiten.
Een relatie heeft een kop en een hoofdtekst.
De kop van de relatie is een set van kenmerken . In de wiskundige verzamelingenleer heeft een verzameling geen volgorde en geen duplicaten. Het is de bedoeling dat u een attribuut identificeert met de naam en niet met een bepaalde positie. Daarom moeten attribuutnamen uniek zijn.
Kunt u identificeren wat de tegenhanger is van een attribuut in SQL? Je hebt waarschijnlijk al geraden dat het een kolom is . SQL heeft echter een idee van de volgorde van de kolommen op basis van hun volgorde van verschijnen in de CREATE TABLE-instructie. Hier is bijvoorbeeld de CREATE TABLE-instructie voor de tabel Sales.Shippers in de TSQLV5-database:
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) );
Vraag de tabel op met de beruchte SELECT *
, zoals zo:
SELECT * FROM Sales.Shippers;
Toen ik deze query in mijn systeem uitvoerde, kreeg ik de volgende uitvoer:
shipperid companyname phone ---------- -------------- --------------- 1 Shipper GVSUA (503) 555-0137 2 Shipper ETYNR (425) 555-0136 3 Shipper ZHISN (415) 555-0138
SQL garandeert dat de kolommen van links naar rechts worden geretourneerd op basis van de definitievolgorde. Ik zal binnenkort uitleggen wat er met de rijen gebeurt. Met SQL kun je zelfs verwijzen naar de ordinale positie van de kolom uit de SELECT-lijst in de ORDER BY-component, zoals (niet dat ik deze oefening aanbeveel, en Aaron Bertrand ook niet):
SELECT shipperid, companyname, phone FROM Sales.Shippers ORDER BY 2;
Deze query genereert de volgende uitvoer:
shipperid companyname phone ---------- -------------- --------------- 2 Shipper ETYNR (425) 555-0136 1 Shipper GVSUA (503) 555-0137 3 Shipper ZHISN (415) 555-0138
De hoofdtekst van een relatie is een set van tupels . Nogmaals, onthoud dat een set geen volgorde heeft en geen duplicaten. Daarom moet een relatie ten minste één kandidaatsleutel hebben waarmee u een tuple uniek kunt identificeren. SQL's tegenhanger van een tuple is een rij . In SQL ben je echter niet gedwongen om een sleutel in een tabel te definiëren, en als je dat niet doet, kun je dubbele rijen krijgen. Zelfs als u wel een sleutel in uw tabel hebt gedefinieerd, kunt u dubbele rijen terugkrijgen van een query op de tabel. Hier is een voorbeeld:
SELECT country FROM HR.Employees;
Deze query genereert de volgende uitvoer:
country -------- USA USA USA USA UK UK UK USA UK
Deze query levert geen relationeel resultaat op vanwege de mogelijkheid van dubbele rijen. Waar relationele theorie gebaseerd is op verzamelingentheorie, is SQL gebaseerd op multisettheorie. Een multiset (ook wel een superset of een tas genoemd) kan duplicaten hebben. SQL geeft je wel een hulpmiddel om duplicaten te elimineren met een DISTINCT-clausule, zoals:
SELECT DISTINCT country FROM HR.Employees;
Deze query genereert de volgende uitvoer:
country -------- UK USA
Wat SQL wel aanhoudt vanuit de relationele theorie in termen van de hoofdtekst van de tabel, is de no-order-eigenschap. Tenzij u een ORDER BY-component in de query toevoegt, heeft u geen enkele garantie dat het resultaat een specifieke volgorde tussen de rijen zal hebben. De hoofdtekst van het bovenstaande zoekresultaat is dus relationeel, althans in die zin dat het geen duplicaten heeft en geen gegarandeerde volgorde heeft.
Stel dat u een query uitvoert op een tabel in SQL Server en dat u geen ORDER BY-component in de query opneemt. Verwacht u dat SQL Server de rijen altijd in een bepaalde volgorde retourneert als een gegarandeerd gedrag? Veel mensen doen dat. Velen denken dat u de rijen altijd terugkrijgt op basis van geclusterde indexvolgorde. Dat is een goed voorbeeld van het negeren van het principe van fysieke gegevensonafhankelijkheid en het maken van aannames op basis van intuïtie en misschien op basis van eerder waargenomen gedrag. Microsoft weet dat een SQL-query zonder een ORDER BY-clausule geen enkele volgorde tussen de resultaatrijen garandeert, en dus zelfs als de gegevens zich op fysiek niveau in een indexstructuur bevinden, hoeft SQL Server de gegevens niet in index te verwerken volgorde. Het kan ervoor kiezen, onder bepaalde fysieke omstandigheden, om dit te doen, maar het kan ervoor kiezen om dit niet te doen onder andere fysieke omstandigheden. Bedenk ook dat de details van de fysieke implementatie kunnen veranderen tussen verschillende versies en builds van het product. Als u wilt garanderen dat de query de resultaatrijen in een bepaalde volgorde retourneert, kunt u dit alleen garanderen door een ORDER BY-component in de buitenste query in te voeren.
Zoals je waarschijnlijk hebt begrepen, zagen de ontwerpers van SQL het niet echt als een prioriteit om de relationele theorie te volgen. En wat ik hier heb beschreven, zijn slechts enkele voorbeelden. Er zijn veel meer. Zoals eerder vermeld, is het mijn doel in dit artikel om voldoende kritische theoretische achtergrond te bieden om de verwarring rond tabeluitdrukkingen op te heffen, voordat ik in toekomstige artikelen in de details van T-SQL ga duiken.
Wat is een tabeluitdrukking?
Relationele algebra (de algebra die bewerkingen op relaties definieert in relationele theorie) heeft een afsluiting eigendom. Wat het betekent is dat een operatie op relaties een relatie oplevert. Een relationele operator werkt op een of meer relaties als input en levert een enkele relatie op als output. Met de eigenschap sluiting kunt u bewerkingen nesten. Een relationele uitdrukking is een uitdrukking die op relaties werkt en een relatie retourneert. Een relationele uitdrukking kan daarom worden gebruikt waar relationele algebra een relatie verwacht.
Als je erover nadenkt, is het niet anders dan bewerkingen op gehele getallen die een geheel getal opleveren. Stel dat de variabele @i een integer-variabele is. De uitdrukking @i + 42 levert een geheel getal op en kan daarom worden gebruikt waar een geheel getal wordt verwacht, zoals in (@i + 42) * 2.
Aangezien een tabel in SQL de tegenhanger is van een relatie in de relationele theorie, hoewel niet erg succesvol, is een tabeluitdrukking in SQL de tegenhanger van een relationele uitdrukking. Zoals eerder vermeld, gebruik ik de term tabeluitdrukking volgend op het gebruik van deze term door C. J. Dates. De SQL-standaard heeft een hele reeks verwarrende termen, waarvan ik bang ben dat sommige niet erg geschikt zijn. De SQL-standaard gebruikt bijvoorbeeld de term tabelexpressie om specifiek een expressie te beschrijven op basis van de query-clausules die beginnen met een verplichte FROM-clausule, en met optioneel de clausules WHERE, GROUP BY, HAVING en WINDOW (de laatste wordt niet ondersteund in T -SQL), en exclusief de SELECT-component. Hier is de specificatie van de standaard:
7.4
Functie
Geef een tafel of een gegroepeerde tafel op.
Formaat
Het is waar dat de uitkomst van wat de standaard een tabeluitdrukking noemt, als een tabel wordt beschouwd, maar u kunt een dergelijke uitdrukking niet als een op zichzelf staande query gebruiken. De datumversie van de term tabeluitdrukking ligt eigenlijk dichter bij wat de SQL-standaard vraaguitdrukking noemt . Hier is de specificatie van de standaard voor wat het query-expressie noemt:
7.17
Functie
Formaat
7.3
Functie
Formaat
Merk op dat deze specificatie bevat wat T-SQL de algemene tabeluitdrukking noemt, ook al gebruikt de standaard deze term niet echt, maar noemt het gewoon met lijstelement . Merk ook op dat de zogenaamde query-expressie niet gebaseerd hoeft te zijn op een query, maar kan zijn gebaseerd op een zogenaamde tabelwaardeconstructor (het gebruik van een VALUES-clausule om een reeks rijen te construeren). Ten slotte, hoewel de query-expressie van de standaard is gebaseerd op een expressie, retourneert deze een tabel en kan deze worden gebruikt waar normaal een tabel wordt verwacht. Om deze redenen vind ik Date's gebruik van de term tabeluitdrukking veel passender.
Ik kan begrijpen waarom sommigen het stilzwijgen over naamgeving en terminologie misschien een beetje pedant en misschien zelfs tijdverspilling vinden. Ik voel me echter heel anders. Ik geloof dat op elk gebied, een streven om eigennamen en terminologie te gebruiken, je dwingt om de fundamenten goed te bestuderen en na te denken over je kennis. In de hoop dat ik er in dit artikel niet in geslaagd ben je genoeg van je te vervreemden om niet verder te willen gaan met de komende delen in de serie, te beginnen met het artikel van volgende maand, ga ik mijn aandacht richten op de manier waarop de verschillende soorten benoemde tabelexpressies worden afgehandeld met behulp van T-SQL in SQL Server en Azure SQL Database.
[
[
[
[
Geef een tafel op.
[
[
WITH [ RECURSIVE ]
AS
|
[
|
[
|
[
|
[
|
|
TABEL
OVEREENKOMEND [ DOOR
ORDER BY
OFFSET
FETCH { FIRST | VOLGENDE } [
Specificeer een set
VALUES
VALUES
[ { Conclusie