Der var to ting galt med din oprindelige tilgang.
- Ved indsættelse i tabellen blev det aldrig garanteret, at
ORDER BY
påINSERT ... SELECT ... ORDER BY
ville være den rækkefølge, som rækkerne faktisk blev indsat. - Når du vælger fra det, garanterer SQL Server ikke, at
SELECT
uden enORDER BY
returnerer rækkerne i en bestemt rækkefølge, såsom indsættelsesrækkefølge alligevel.
I 2012 ser det ud til, at adfærden har ændret sig i forhold til punkt 1. Den ignorerer nu generelt ORDER BY
på SELECT
sætning, der er kilden til en INSERT
DECLARE @T TABLE(number int)
INSERT INTO @T
SELECT number
FROM master..spt_values
ORDER BY name
2008-plan
2012-plan
Årsagen til ændringen af adfærd er, at SQL Server i tidligere versioner producerede en plan, der blev delt mellem udførelser med SET ROWCOUNT 0
(fra) og SET ROWCOUNT N
. Sorteringsoperatøren var kun der for at sikre den korrekte semantik i tilfælde af at planen blev kørt af en session med en ROWCOUNT
ikke nul sæt. TOP
operatør til venstre for den er en ROWCOUNT TOP
.
SQL Server 2012 producerer nu separate planer for de to sager, så der er ingen grund til at tilføje disse til ROWCOUNT 0
version af planen.
En sortering kan stadig forekomme i planen i 2012, hvis SELECT
har en eksplicit TOP
defineret (andre end TOP 100 PROCENT
), men dette garanterer stadig ikke den faktiske indsættelsesrækkefølge af rækker, planen kan så have en anden sortering efter TOP N
er etableret for at få rækkerne i grupperet indeksrækkefølge for eksempel.
For eksemplet i dit spørgsmål ville jeg bare justere opkaldskoden for at angive ORDER BY name
hvis det er det, det kræver.
Med hensyn til dit sort_id
idé fra Bestillingsgarantier i SQL Server
det er garanteret, når du indsætter i en tabel med IDENTITY
at rækkefølgen disse tildeles vil være i henhold til ORDER BY
så du kunne også gøre
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
men du skal stadig bestille efter sort_id
i dine valgforespørgsler, da der ikke er nogen garanteret bestilling uden det (måske dette sort_id
fremgangsmåde kan være nyttig i det tilfælde, hvor de originale kolonner, der bruges til bestilling, ikke bliver kopieret ind i tabelvariablen)