Dieser Artikel ist der erste einer Reihe über die Grundlagen von Tabellenausdrücken in T-SQL. Ich werde mich hauptsächlich auf vier Arten benannter Tabellenausdrücke konzentrieren, die in T-SQL als abgeleitete Tabellen, allgemeine Tabellenausdrücke (CTEs), Ansichten und Inline-Tabellenwertfunktionen (Inline-TVFs) bekannt sind.
Zu dieser Serie wurde ich von meinem guten Freund Grant Fritchey inspiriert, den ich seit vielen Jahren kenne. Wie Grant wiederholt betont, denken viele, die gängige Tabellenausdrücke in T-SQL verwenden, dass SQL Server die innere Abfrageergebnismenge beibehält, und dass der Grund für diese Annahme die Verwendung des Begriffs Tabelle ist im Namen des Konstrukts. Wenn dieses Thema in Community-Diskussionen auftaucht, wird oft argumentiert, dass die Verwendung des Begriffs Tabelle im Namen des Konstrukts unangemessen ist, da es sich nicht wirklich um eine Tabelle handelt. Es gibt sogar Vorschläge, eine Namenskampagne zu starten, in der Hoffnung, dass zumindest in T-SQL eine zukünftige Namensänderung für dieses Konstrukt zu sehen ist. Einige der Vorschläge beinhalten Abfrageausdruck , Inline-Ansicht , Ansicht auf Anweisungsebene , und andere.
Vielleicht wird dies einige überraschen, aber ich finde tatsächlich die Verwendung des Begriffs Tabelle im allgemeinen Tabellenausdruck als sehr passend. Tatsächlich finde ich die Verwendung des Begriffs Tabellenausdruck wie angemessen. Für mich ist der beste Weg, um zu beschreiben, was ein CTE in T-SQL ist, ein benannter Tabellenausdruck . Dasselbe gilt für das, was T-SQL als abgeleitete Tabellen bezeichnet (das spezifische Sprachkonstrukt im Gegensatz zur allgemeinen Idee), Ansichten und Inline-TVFs. Sie alle sind benannte Tabellenausdrücke.
Wenn Sie etwas Geduld mit mir haben, werde ich in diesem Artikel meine Sicht der Dinge begründen. Mir kam der Gedanke, dass sowohl die Namensverwirrung als auch die Verwirrung darüber, ob Tabellenausdrücke einen Persistenzaspekt haben, mit einem besseren Verständnis der Grundlagen unseres Gebiets der relationalen Datenbankverwaltungssysteme geklärt werden können. Diese Grundlagen sind relationale Theorie, wie sich SQL (die Standardsprache) darauf bezieht und wie sich der T-SQL-Dialekt, der in den Implementierungen von SQL Server und Azure SQL-Datenbank verwendet wird, auf beide bezieht.
Als Ausgangspunkt möchten Sie die folgenden Fragen beantworten können:
- Was bedeutet die physische Datenunabhängigkeit Prinzip im relationalen Modell bedeuten?
- Was ist eine Tabelle in SQL und was ist das Gegenstück im relationalen Modell?
- Was ist die Abschlusseigenschaft der relationalen Algebra?
- Was ist ein Tabellenausdruck und was ist das Gegenstück im relationalen Modell?
Sobald Sie in der Lage sind, die obigen Fragen richtig zu beantworten, werden Sie sehr wahrscheinlich die Verwendung des Begriffs benannter Tabellenausdruck finden entsprechend den oben genannten Konstrukten (was T-SQL abgeleitete Tabellen, CTEs, Ansichten und Inline-TVFs nennt).
Ich möchte nicht so klingen, als hätte ich ein sehr tiefes Verständnis der relationalen Theorie. Meine Expertise ist T-SQL. Ich gebe zu, dass es viel mehr gibt, was ich über relationale Theorie nicht weiß, als ich selbst, und dass einige Dinge, von denen ich glaube, dass ich sie weiß, einfach nicht so sind. Wenn ich die Schriften von C. J. Dates zu diesem Thema lese, habe ich das Gefühl, dass ich kaum an der Oberfläche dessen kratze, was es zu wissen gibt, und dass ich mich bemühen könnte und sollte, es besser zu verstehen. Ich erkenne an und bin fest davon überzeugt, dass ein gutes Verständnis der relationalen Theorie direkt zu einem besseren Verständnis von SQL und T-SQL und zum Schreiben von besserem, genauerem und robusterem T-SQL-Code führt. Allen, die sich für Daten als Karriere entschieden haben, empfehle ich die Lektüre von SQL and Relational Theory:How to Write Accurate SQL Code 3rd Edition von C. J. Date (O'Reilly 2015).
Im ersten Teil dieser Serie möchte ich ein Verständnis für meine Verwendung der Begriffe Tabellenausdruck herstellen und benannter Tabellenausdruck , was mit der Verwendung dieses Begriffs durch Date und leider nicht mit der Verwendung dieses Begriffs durch den SQL-Standard übereinstimmt. Um dies zu erreichen, werde ich ein wenig Hintergrundwissen aus der relationalen Theorie und dem SQL-Standard liefern. Aber wie gesagt, ich empfehle, das Buch von Date zu lesen, um dieses Thema wirklich detailliert zu behandeln.
Ich beginne damit, zu erklären, was das Prinzip der physischen Datenunabhängigkeit bedeutet. Als Nächstes erkläre ich, was eine Tabelle in SQL und ihr Gegenstück in der relationalen Theorie ist. Ich werde dann erklären, was die Abschlusseigenschaft der relationalen Algebra bedeutet. Sobald Sie eine vernünftige Vorstellung davon haben, was eine Tabelle ist und was die Abschlusseigenschaft bedeutet, wird es ziemlich einfach zu verstehen, was ein Tabellenausdruck ist. Mein Fokus wird sich dann den Besonderheiten in T-SQL zuwenden. Ich habe viel über die Grundlagen von Tabellenausdrücken in T-SQL zu sagen – sowohl in Bezug auf die konzeptionelle Behandlung als auch in Bezug auf die Implementierungsdetails, einschließlich der physischen Darstellung und Überlegungen zur Abfrageoptimierung.
Ich finde dieses Thema spannend und sehr praxisnah, wenn man sich einmal mit den Details der Umsetzung beschäftigt. Tatsächlich habe ich so viel darüber zu sagen, dass ich nicht sicher bin, wie viele Teile diese Serie letztendlich umfassen wird. Was ich Ihnen mit großer Zuversicht sagen kann, ist, dass es mehrere Teile geben wird. Wahrscheinlich mehr als einer und weniger als 100. In zukünftigen Teilen werde ich mich mit den einzelnen Arten benannter Tabellenausdrücke, Modifikationsüberlegungen, Inlining-Aspekten, Ordnungsaspekten, Korrelationen und mehr befassen.
In meinen Beispielen verwende ich eine Beispieldatenbank namens TSQLV5. Das Skript, das diese Datenbank erstellt und füllt, finden Sie hier und ihr ER-Diagramm hier.
Physische Datenunabhängigkeit
Die Unabhängigkeit von physischen Daten ist ein Prinzip der relationalen Theorie, das besagt, dass die Details der physischen Implementierung vor dem Benutzer, der die Abfragen an das relationale Datenbankverwaltungssystem sendet, verborgen oder für ihn transparent sein sollten. In den Abfragen sollen sich Benutzer auf was konzentrieren Sie müssen logische Operationen verwenden, die auf relationaler Algebra basieren, im Gegensatz zu wie um die Daten zu erhalten. Sie sollen sich keine Gedanken darüber machen, wie die Daten strukturiert, abgerufen und verarbeitet werden. Solche physischen Implementierungsdetails neigen dazu, sich zwischen verschiedenen Implementierungen (RDBMS-Produkten) erheblich zu unterscheiden. Selbst bei demselben RDBMS ändern sich die Details der physischen Implementierung manchmal zwischen verschiedenen Versionen und Builds. Die Idee hinter dem Prinzip der physischen Datenunabhängigkeit besteht theoretisch darin, die Investition der Benutzer zu schützen, indem die Notwendigkeit entfällt, Ihre Lösungen zu überarbeiten, wenn Sie Ihr RDBMS auf eine neue Version aktualisieren oder sogar wenn Sie von einem RDBMS zu einem anderen migrieren. Wie Sie wahrscheinlich wissen, sind die Dinge in der Praxis nicht so einfach, aber das ist ein Thema für eine andere Diskussion.
Was ist eine Tabelle?
Wenn Sie eine Weile mit T-SQL oder einem anderen SQL-Dialekt gearbeitet haben, entwickeln Sie ein intuitives Verständnis dafür, was eine Tabelle ist. Das Problem ist, dass ohne einen gewissen Hintergrund der Beziehungstheorie das intuitive Verständnis oft nicht sehr genau ist. Ein typischer Fehler ist, dass wir uns intuitiv eher auf Details der physischen Umsetzung konzentrieren. Wenn Sie beispielsweise darüber nachdenken, was eine Tabelle ist, denken Sie an eine Tabelle als logische Struktur (eine Reihe von Zeilen) oder an physische Implementierungsdetails in der Plattform, die Sie verwenden (in SQL Server , Seiten, Extents, Heap versus Clustered-Index, Nonclustered-Indizes usw.)? Als Benutzer, der SQL-Code zum Abfragen einer Tabelle schreibt, sollten Sie sich die Tabelle nach dem Prinzip der physischen Datenunabhängigkeit als logische Struktur vorstellen und das RDBMS sich um die Details der physischen Implementierung kümmern lassen. Gehen wir also einen Schritt zurück und versuchen herauszufinden, was eine Tabelle ist.
Eine Tabelle ist das Gegenstück von SQL zur Hauptstruktur in der relationalen Theorie – einer Relation. Um die Dinge einfach zu halten und den Umfang meiner Berichterstattung einzuschränken, werde ich nicht auf die Unterscheidung zwischen einer Beziehungsvariablen und einem Beziehungswert eingehen. Wenn Sie meiner Empfehlung folgen und das Buch von Date lesen, werden Sie sehr schnell ein klares Bild von solchen Feinheiten haben.
Eine Relation hat eine Überschrift und einen Körper.
Die Überschrift der Relation ist ein set von Attributen . In der mathematischen Mengenlehre hat eine Menge keine Ordnung und keine Duplikate. Sie sollten ein Attribut anhand des Namens und nicht anhand einer Position identifizieren. Folglich müssen Attributnamen eindeutig sein.
Können Sie erkennen, was das Gegenstück zu einem Attribut in SQL ist? Sie haben wahrscheinlich schon erraten, dass es sich um eine Spalte handelt . SQL hat jedoch tatsächlich eine Vorstellung von der Reihenfolge seiner Spalten, die auf der Reihenfolge ihres Erscheinens in der CREATE TABLE-Anweisung basiert. Hier ist zum Beispiel die CREATE TABLE-Anweisung für die Sales.Shippers-Tabelle in der TSQLV5-Datenbank:
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) );
Fragen Sie die Tabelle mit dem berüchtigten SELECT *
ab , etwa so:
SELECT * FROM Sales.Shippers;
Als ich diese Abfrage in meinem System ausführte, erhielt ich die folgende Ausgabe:
shipperid companyname phone ---------- -------------- --------------- 1 Shipper GVSUA (503) 555-0137 2 Shipper ETYNR (425) 555-0136 3 Shipper ZHISN (415) 555-0138
SQL garantiert, dass die Spalten basierend auf der Definitionsreihenfolge von links nach rechts zurückgegeben werden. Was mit den Zeilen passiert, erkläre ich gleich. SQL erlaubt Ihnen sogar, auf die Ordinalposition der Spalte aus der SELECT-Liste in der ORDER BY-Klausel zu verweisen, etwa so (nicht, dass ich diese Vorgehensweise empfehle, und Aaron Bertrand auch nicht):
SELECT shipperid, companyname, phone FROM Sales.Shippers ORDER BY 2;
Diese Abfrage generiert die folgende Ausgabe:
shipperid companyname phone ---------- -------------- --------------- 2 Shipper ETYNR (425) 555-0136 1 Shipper GVSUA (503) 555-0137 3 Shipper ZHISN (415) 555-0138
Der Körper einer Beziehung ist eine Menge von Tupeln . Erinnern Sie sich noch einmal daran, dass eine Menge keine Ordnung und keine Duplikate hat. Daher muss eine Relation mindestens einen Kandidatenschlüssel haben, mit dem Sie ein Tupel eindeutig identifizieren können. Das SQL-Gegenstück zu einem Tupel ist eine Zeile . In SQL sind Sie jedoch nicht gezwungen, einen Schlüssel in einer Tabelle zu definieren, und wenn Sie dies nicht tun, können Sie mit doppelten Zeilen enden. Selbst wenn Sie einen Schlüssel in Ihrer Tabelle definiert haben, können Sie doppelte Zeilen von einer Abfrage der Tabelle erhalten. Hier ist ein Beispiel:
SELECT country FROM HR.Employees;
Diese Abfrage generiert die folgende Ausgabe:
country -------- USA USA USA USA UK UK UK USA UK
Diese Abfrage erzeugt aufgrund der Möglichkeit doppelter Zeilen kein relationales Ergebnis. Während die relationale Theorie auf der Mengentheorie basiert, basiert SQL auf der Multimengentheorie. Ein Multiset (auch bekannt als Superset oder Bag) kann Duplikate haben. SQL gibt Ihnen ein Werkzeug, um Duplikate mit einer DISTINCT-Klausel zu eliminieren, etwa so:
SELECT DISTINCT country FROM HR.Employees;
Diese Abfrage generiert die folgende Ausgabe:
country -------- UK USA
Was SQL in Bezug auf den Tabellenkörper von der relationalen Theorie beibehält, ist die No-Order-Eigenschaft. Wenn Sie der Abfrage keine ORDER BY-Klausel hinzufügen, haben Sie keine Gewissheit, dass das Ergebnis eine bestimmte Reihenfolge zwischen den Zeilen hat. Der Hauptteil des obigen Abfrageergebnisses ist also relational, zumindest in dem Sinne, dass es keine Duplikate und keine garantierte Reihenfolge gibt.
Angenommen, Sie fragen eine Tabelle in SQL Server ab und fügen keine ORDER BY-Klausel in die Abfrage ein. Erwarten Sie, dass SQL Server die Zeilen als garantiertes Verhalten immer in einer bestimmten Reihenfolge zurückgibt? Viele Leute tun es. Viele denken, dass Sie die Zeilen immer basierend auf der Clustered-Index-Reihenfolge zurückerhalten. Das ist ein gutes Beispiel dafür, das Prinzip der physikalischen Datenunabhängigkeit zu ignorieren und Annahmen zu treffen, die auf Intuition und vielleicht auf in der Vergangenheit beobachtetem Verhalten basieren. Microsoft weiß, dass eine SQL-Abfrage ohne eine ORDER BY-Klausel keine Reihenfolge zwischen den Ergebniszeilen garantiert, und selbst wenn sich die Daten auf der physischen Ebene in einer Indexstruktur befinden, muss SQL Server die Daten nicht im Index verarbeiten Befehl. Es kann sich unter bestimmten physikalischen Bedingungen dafür entscheiden, aber es kann sich unter anderen physikalischen Bedingungen dafür entscheiden, dies nicht zu tun. Denken Sie auch daran, dass sich die Details der physischen Implementierung zwischen verschiedenen Versionen und Builds des Produkts ändern können. Wenn Sie garantieren möchten, dass die Abfrage die Ergebniszeilen in einer bestimmten Reihenfolge zurückgibt, können Sie dies nur sicherstellen, indem Sie eine ORDER BY-Klausel in die äußerste Abfrage einfügen.
Wie Sie wahrscheinlich mitbekommen haben, sahen die Designer von SQL es nicht wirklich als Priorität an, der relationalen Theorie zu folgen. Und was ich hier beschrieben habe, sind nur einige Beispiele. Es gibt viele mehr. Wie bereits erwähnt, ist mein Ziel in diesem Artikel lediglich, genügend kritischen theoretischen Hintergrund bereitzustellen, um die Verwirrung um Tabellenausdrücke zu beseitigen, bevor ich mich in zukünftigen Artikeln mit den Besonderheiten von T-SQL befasse.
Was ist ein Tabellenausdruck?
Relationale Algebra (die Algebra, die Operationen mit Beziehungen in der relationalen Theorie definiert) hat eine Schließung Eigentum. Was es bedeutet ist, dass eine Operation auf Relationen eine Relation ergibt. Ein relationaler Operator bearbeitet eine oder mehrere Relationen als Eingabe und liefert eine einzelne Relation als Ausgabe. Die Closure-Eigenschaft ermöglicht es Ihnen, Operationen zu verschachteln. Ein relationaler Ausdruck ist ein Ausdruck, der Beziehungen bearbeitet und eine Beziehung zurückgibt. Ein relationaler Ausdruck kann daher dort verwendet werden, wo die relationale Algebra eine Relation erwartet.
Wenn Sie darüber nachdenken, ist es nicht anders als Operationen mit ganzen Zahlen, die ein ganzzahliges Ergebnis liefern. Angenommen, die Variable @i ist eine ganzzahlige Variable. Der Ausdruck @i + 42 ergibt eine ganze Zahl und kann daher dort verwendet werden, wo eine ganze Zahl erwartet wird, wie in (@i + 42) * 2.
Da eine Tabelle in SQL das Gegenstück zu einer Relation in der relationalen Theorie ist, wenn auch nicht sehr erfolgreich, ist ein Tabellenausdruck in SQL das Gegenstück zu einem relationalen Ausdruck. Wie bereits erwähnt, verwende ich den Begriff Tabellenausdruck in Anlehnung an die Verwendung dieses Begriffs durch C. J. Dates. Der SQL-Standard enthält eine Menge verwirrender Begriffe, von denen einige, fürchte ich, nicht sehr angemessen sind. Beispielsweise verwendet der SQL-Standard den Begriff Tabellenausdruck, um speziell einen Ausdruck zu beschreiben, der auf Abfrageklauseln basiert, die mit einer obligatorischen FROM-Klausel beginnen und optional die Klauseln WHERE, GROUP BY, HAVING und WINDOW enthalten (letztere wird in T -SQL) und ohne die SELECT-Klausel. Hier ist die Spezifikation des Standards:
7.4
Funktion
Geben Sie eine Tabelle oder eine gruppierte Tabelle an.
Formatieren
Es stimmt, dass das Ergebnis dessen, was der Standard einen Tabellenausdruck nennt, als Tabelle angesehen wird, aber Sie können einen solchen Ausdruck nicht als eigenständige Abfrage verwenden. Die Date-Version des Term-Tabellenausdrucks ist eigentlich näher an dem, was der SQL-Standard Abfrageausdruck nennt . Hier ist die Spezifikation des Standards für das, was er Abfrageausdruck nennt:
7.17
Funktion
Formatieren
7.3
Funktion
Formatieren
Beachten Sie, dass diese Spezifikation das enthält, was T-SQL als allgemeinen Tabellenausdruck bezeichnet, obwohl der Standard diesen Begriff nicht wirklich verwendet, sondern nur mit Listenelement nennt . Beachten Sie auch, dass der sogenannte Abfrageausdruck nicht auf einer Abfrage basieren muss, sondern auf einem sogenannten Tabellenwertkonstruktor basieren könnte (die Verwendung einer VALUES-Klausel zum Erstellen einer Reihe von Zeilen). Schließlich gibt der Abfrageausdruck des Standards, obwohl er auf einem Ausdruck basiert, eine Tabelle zurück und kann dort verwendet werden, wo normalerweise eine Tabelle erwartet wird. Aus diesen Gründen finde ich die Verwendung des Begriffs Tabellenausdruck durch Date viel angemessener.
Ich kann verstehen, warum einige das Verweilen bei der Benennung und Terminologie als etwas pedantisch und vielleicht sogar als Zeitverschwendung empfinden. Allerdings empfinde ich das ganz anders. Ich glaube, dass das Bestreben, Eigennamen und Terminologie zu verwenden, Sie in jedem Bereich dazu zwingt, die Grundlagen gut zu studieren, und über Ihr Wissen nachdenkt. In der Hoffnung, dass es mir in diesem Artikel nicht gelungen ist, Sie so weit vor den Kopf zu stoßen, dass Sie nicht mit den kommenden Teilen der Serie fortfahren möchten, werde ich mich ab dem Artikel im nächsten Monat auf die Art und Weise konzentrieren, wie die verschiedenen Arten benannt werden Tabellenausdrücke werden mithilfe von T-SQL in SQL Server und Azure SQL-Datenbank verarbeitet.
[
[
[
[
Geben Sie eine Tabelle an.
[
[
WITH [ RECURSIVE ]
AS [
|
[
|
[
|
[
|
[
|
|
TABLE
CORRESPONDING [ BY
ORDER BY
OFFSET
FETCH { FIRST | WEITER } [
|
Geben Sie einen Satz von
VALUES
VALUES
[ { Schlussfolgerung