Det var två saker fel med ditt ursprungliga tillvägagångssätt.
- När du infogade i tabellen var det aldrig garanterat att
ORDER BY
påINSERT ... SELECT ... ORDER BY
skulle vara den ordning som raderna faktiskt infogades. - När du väljer från den garanterar inte SQL Server att
SELECT
utan enORDER BY
kommer att returnera raderna i vilken ordning som helst, såsom insättningsordning ändå.
Under 2012 ser det ut som om beteendet har ändrats med avseende på punkt 1. Den ignorerar nu generellt ORDER BY
på SELECT
sats som är källan till en INSERT
DECLARE @T TABLE(number int)
INSERT INTO @T
SELECT number
FROM master..spt_values
ORDER BY name
2008-plan
2012-plan
Anledningen till beteendeförändringen är att SQL Server i tidigare versioner producerade en plan som delades mellan körningar med SET ROWCOUNT 0
(av) och SET ROWCOUNT N
. Sorteringsoperatorn var bara där för att säkerställa korrekt semantik om planen kördes av en session med en ROWCOUNT
som inte är noll uppsättning. TOPP
operatorn till vänster om den är en ROWCOUNT TOP
.
SQL Server 2012 producerar nu separata planer för de två fallen så det finns inget behov av att lägga till dessa i ROWCOUNT 0
version av planen.
En sortering kan fortfarande visas i planen under 2012 om SELECT
har en explicit TOPP
definierade (annat än TOPP 100 PROCENT
) men detta garanterar fortfarande inte faktisk insättningsordning för rader, planen kan då ha en annan sortering efter TOP N
är etablerad för att till exempel få raderna i klustrad indexordning.
För exemplet i din fråga skulle jag bara justera anropskoden för att specificera ORDER BY name
om det är vad det kräver.
Angående ditt sort_id
idé från Beställningsgarantier i SQL Server
det garanteras när du infogar i en tabell med IDENTITY
att ordningen dessa tilldelas kommer att vara enligt ORDER BY
så kan du också göra
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 skulle fortfarande behöva beställa med sort_id
i dina valfrågor eftersom det inte finns någon garanterad beställning utan det (kanske detta sort_id
tillvägagångssätt kan vara användbart i de fall där originalkolumnerna som används för beställning inte kopieras till tabellvariabeln)