Wann wird die SELECT… INTO-Anweisung (PE003) verwendet?
Wir können SELECT…INTO
in SQL Server verwenden, um eine neue Tabelle aus einer Tabellenquelle zu erstellen. SQL Server verwendet die Attribute der Ausdrücke in der Liste SELECT
, um die Struktur der neuen Tabelle zu definieren.
Verwenden Sie vor SQL Server 2005 die Verwendung von SELECT…INTO
im Produktionscode war ein Leistungscodegeruch, da Schemasperren für Systemtabellen der Datenbank erworben wurden und SQL Server während der Ausführung der Abfrage nicht mehr reagierte. Dies liegt daran, dass es sich um eine DDL-Anweisung in einer impliziten Transaktion handelt, die unweigerlich lange dauert, da die Daten in dieselbe SQL-Anweisung eingefügt werden. Dieses Verhalten wurde jedoch in SQL Server 2005 behoben, als sich das Sperrmodell änderte.
SELECT…INTO
wurde populär, da es eine schnellere Methode zum Einfügen von Daten war als die Verwendung von INSERT
INTO…SELECT…
. Dies war hauptsächlich darauf zurückzuführen, dass die Operation SELECT…INTO
nach Möglichkeit massenprotokolliert wurde. Obwohl INSERT
INTO
jetzt massenprotokolliert werden kann, wird dieser Leistungsvorteil möglicherweise in SQL Server 2012 und 2014 angezeigt, da SELECT…INTO
kann in diesen Versionen parallelisiert werden, während die Unterstützung für die Parallelisierung von INSERT
INTO
nur in SQL Server aufgetreten ist 2016. Mit SELECT…INTO
haben Sie jedoch weiterhin die Aufgabe, alle erforderlichen Indizes und Einschränkungen usw. für die neue Tabelle zu definieren.
Eine Empfehlung an Vermeiden Sie die Verwendung von SELECT…INTO
für Produktionscode, der in SQL Prompt (PE003) als Code-Analyseregel enthalten ist.
Erstellen von Tabellen mit der Anweisung SELECT INTO
Die Funktion SELECT…INTO
in SQL Server wurde entwickelt, um eine Tabellenquelle als Teil eines Prozesses zu speichern oder zu „persistieren“. Hier ein einfaches Beispiel:
Eine Tabellenquelle kann jedoch viele andere Dinge als eine herkömmliche Tabelle sein, z. B. eine benutzerdefinierte Funktion, eine OpenQuery
, eine OpenDataSource
, eine OPENXML
-Klausel, eine abgeleitete Tabelle, eine verknüpfte Tabelle, eine schwenkbare Tabelle, eine entfernte Datenquelle, eine Tabellenvariable oder eine variable Funktion. Mit diesen exotischeren Tabellenquellen wird die Syntax SELECT…INTO
nützlicher.
SELECT INTO Teil des ANSI Standard?
Die ANSI-Standards unterstützen ein SELECT…INTO
-Konstrukt. Es wird als Singleton-Auswahl bezeichnet und lädt eine einzelne Zeile mit Werten, wird jedoch nur sehr selten verwendet (Dank an Joe Celko für diesen Hinweis).
Benutzer verwenden häufig SELECT…INTO
mit dem Missverständnis, dass dies eine schnelle Methode zum Kopieren von Tabellen ist. Daher ist es überraschend, dass keiner der Indizes, Einschränkungen, berechneten Spalten oder Trigger in definiert ist Die Quelltabelle wird in die neue Tabelle übertragen. Sie können auch nicht in der Anweisung SELECT…INTO
angegeben werden. Es wird auch nichts gegen die Nullfähigkeit oder die Beibehaltung berechneter Spalten unternommen. Alle diese Aufgaben müssen nachträglich mit den vorhandenen Daten ausgeführt werden, was zwangsläufig einige Zeit in Anspruch nimmt.
Sie können jedoch die Funktion IDENTITY
(Datentyp, Startwert,) verwenden. Inkrement), um ein Identitätsfeld einzurichten, und wenn die Quelle eine einzelne Tabelle ist, ist es möglich, eine Spalte der Zieltabelle in eine Identitätsspalte zu verwandeln. Aufgrund dieser Tatsache gehen Entwickler wahrscheinlich davon aus, dass andere Spaltenattribute übertragen werden.
Außerdem können keine partitionierten Tabellen, spärlichen Spalten oder andere von einer Quelltabelle geerbte Attribute erstellt werden. Wie könnte es sein, wenn die Daten aus einer Abfrage mit vielen Verknüpfungen oder aus einer exotischen externen Datenquelle stammen?
Seit SQL 2012 SP1 CU10 kann SELECT…INTO
parallel ausgeführt werden. Seit SQL Server 2016 ist das parallele Einfügen für die herkömmliche INSERT INTO…SELECT
-Anweisung mit bestimmten Einschränkungen zulässig, sodass jeder Leistungsvorteil der Verwendung von … INTO
ist jetzt eher verkleinert. Der INSERT
INTO
-Prozess kann auch beschleunigt werden, wenn er durch Festlegen des Wiederherstellungsmodells massenprotokolliert und nicht vollständig wiederhergestellt werden kann zu einfach oder massenweise protokolliert, in eine leere Tabelle oder einen Heap einfügen und den TABLOCK
-Hinweis für die Tabelle festlegen.
Im Folgenden werden einige der Einschränkungen und zusammengefasst Einschränkungen bei Verwendung von SELECT…INTO
.
- Die
IDENTITY
-Eigenschaft einer Spalte wird übertragen, jedoch nicht, wenn:- Die Anweisung
SELECT
enthält verknüpfte Tabellen (entweder mitJOIN
oderUNION
),GROUP
BY
-Klausel oder Aggregatfunktion.Wenn Sie vermeiden möchten, dass eineIDENTITY
-Eigenschaft in die neue Tabelle übertragen wird, aber die Werte der Spalte benötigen, sollten Sie eineJOIN
zu Ihrer Tabellenquelle unter einer Bedingung, die niemals wahr ist, oder zu einerUNION
, die keine Zeilen bereitstellt. - Die
IDENTITY
wird mehr als einmal in der ListeSELECT
- aufgeführt. Die Spalte
IDENTITY
ist Teil eines Ausdrucks - Die Spalte
IDENTITY
stammt aus einer entfernten Datenquelle
- Die Anweisung
- Sie können nicht
SELECT…INTO
entweder ein tabellenwertiger Parameter oder eine Tabellenvariable als Ziel, obwohl Sie sieFROM
auswählen können. - Auch wenn Ihre Quelle ist eine partitionierte Tabelle. Die neue Tabelle wird in der Standarddateigruppe erstellt. In SQL Server 2017 ist es jedoch möglich, die Dateigruppe, in der die Zieltabelle erstellt wird, über die Klausel
ON
anzugeben. - Sie können eine
ORDER
BY
-Klausel, wird jedoch im Allgemeinen ignoriert. Aus diesem Grund ist die Reihenfolge vonIDENTITY_INSERT
nicht garantiert. - Wenn eine berechnete Spalte in
SELECT
Liste, die entsprechende Spalte in der neuen Tabelle ist keine berechnete Spalte. Die Werte in der neuen Spalte sind die Werte, die zum Zeitpunkt der Ausführung vonSELECT…INTO
berechnet wurden. - Wie bei einem
CREATE
TABLE
-Anweisung Wenn eineSELECT…INTO
-Anweisung in einer expliziten Transaktion enthalten ist, sind die zugrunde liegenden Zeilen in den betroffenen Systemtabellen ausschließlich gesperrt, bis die Transaktion explizit festgeschrieben wird. In der Zwischenzeit führt dies zu Blockierungen bei anderen Prozessen, die diese Systemtabellen verwenden.
Es gibt einige Verwirrung über Probleme, die bei der Verwendung von SELECT…INTO
mit temporären Tabellen. SELECT…INTO
hat dafür einen etwas unfairen Ruf erlangt, war jedoch Teil eines allgemeineren Problems mit Latch-Konflikten in tempdb
unter hoher Last der Erstellung und Löschung kleiner temporärer Tabellen. Wenn SELECT…INTO
mit Begeisterung angenommen wurde, könnte dies diese Art von Aktivität erheblich steigern. Das Problem kann ab SQL Server 2000 leicht behoben werden, indem das Trace-Flag TF1118 eingeführt wird, das ab SQL Server 2016 nicht mehr erforderlich ist. Eine vollständige Erklärung finden Sie unter Missverständnisse in Bezug auf TF 1118.
Zusammenfassung
Zusammenfassend ist SELECT…INTO
eine gute Möglichkeit, eine Tabelle zu erstellen. Die Quelle bleibt als Teil eines Prozesses vorübergehend erhalten, wenn Sie sich nicht um Einschränkungen, Indizes oder spezielle Spalten kümmern. Es ist keine gute Möglichkeit, eine Tabelle zu kopieren, da nur die wichtigsten Elemente des Tabellenschemas kopiert werden können. Im Laufe der Jahre gab es Faktoren, die die Anziehungskraft von SELECT…INTO
erhöht oder verringert haben. Insgesamt ist es jedoch eine gute Idee, die Verwendung nach Möglichkeit zu vermeiden. Erstellen Sie stattdessen explizit eine Tabelle mit allen Funktionen, über die die Tabelle verfügt, um sicherzustellen, dass die Daten konsistent sind.