An Ihrem ursprünglichen Ansatz waren zwei Dinge falsch.
- Beim Einfügen in die Tabelle war nie garantiert, dass der
ORDER BY
aufINSERT ... SELECT ... ORDER BY
wäre die Reihenfolge, in der die Zeilen tatsächlich eingefügt wurden. - Bei der Auswahl daraus garantiert SQL Server nicht, dass
SELECT
ohneORDER BY
gibt die Zeilen ohnehin in einer bestimmten Reihenfolge zurück, z. B. in der Reihenfolge der Einfügungen.
Im Jahr 2012 sieht es so aus, als ob sich das Verhalten bezüglich Punkt 1 geändert hat. Es ignoriert nun generell den ORDER BY
auf SELECT
-Anweisung, die die Quelle für ein INSERT
ist
DECLARE @T TABLE(number int)
INSERT INTO @T
SELECT number
FROM master..spt_values
ORDER BY name
2008-Plan
2012-Plan
Der Grund für die Verhaltensänderung liegt darin, dass SQL Server in früheren Versionen einen Plan erstellt hat, der zwischen Ausführungen mit SET ROWCOUNT 0
geteilt wurde (aus) und SET ROWCOUNT N
. Der Sortieroperator war nur dazu da, die korrekte Semantik sicherzustellen, falls der Plan von einer Sitzung mit einem ROWCOUNT
ungleich Null ausgeführt wurde einstellen. Die TOP
links davon ist ein ROWCOUNT TOP
.
SQL Server 2012 erstellt jetzt separate Pläne für die beiden Fälle, sodass diese nicht zu ROWCOUNT 0
hinzugefügt werden müssen Version des Plans.
Eine Sortierung kann 2012 noch im Plan erscheinen, wenn der SELECT
hat ein explizites TOP
definiert (anders als TOP 100 PERCENT
), aber dies garantiert immer noch nicht die tatsächliche Einfügungsreihenfolge der Zeilen, der Plan könnte dann eine andere Sortierung nach TOP N
haben wird eingerichtet, um die Zeilen zum Beispiel in die Clustered-Index-Reihenfolge zu bringen.
Für das Beispiel in Ihrer Frage würde ich einfach den Aufrufcode anpassen, um ORDER BY name
anzugeben wenn es das erfordert.
Zu Ihrer sort_id
Idee von Ordnen von Garantien in SQL Server
es ist beim Einfügen in eine Tabelle mit IDENTITY
gewährleistet dass die Reihenfolge, in der diese zugewiesen werden, der ORDER BY
entspricht Sie könnten also auch
DECLARE @Customer TABLE (
Sort_Id INT IDENTITY PRIMARY KEY,
Customer_ID INT,
Name INT,
Expired BIT )
INSERT INTO @Customer
SELECT Customer_ID,
Name,
CASE
WHEN Expiry_Date < Getdate() THEN 1
WHEN Expired = 1 THEN 1
ELSE 0
END
FROM Customer
ORDER BY Name
aber Sie müssten trotzdem nach der sort_id
sortieren in Ihren Auswahlabfragen, da es ohne diese keine garantierte Sortierung gibt (vielleicht diese sort_id
Dieser Ansatz kann nützlich sein, wenn die ursprünglichen Spalten, die zum Sortieren verwendet wurden, nicht in die Tabellenvariable kopiert werden)