C'erano due cose che non andavano nel tuo approccio originale.
- Al momento dell'inserimento nella tabella non è mai stato garantito che il
ORDER BY
sulINSERT ... SELECT ... ORDER BY
sarebbe l'ordine in cui le righe sono state effettivamente inserite. - Se si seleziona da esso, SQL Server non garantisce che
SELECT
senza unORDER BY
restituirà comunque le righe in un ordine particolare come l'ordine di inserzione.
Nel 2012 sembra che il comportamento sia cambiato rispetto all'articolo 1. Ora generalmente ignora il ORDER BY
sul SELECT
istruzione che è l'origine di un INSERT
DECLARE @T TABLE(number int)
INSERT INTO @T
SELECT number
FROM master..spt_values
ORDER BY name
Piano 2008
Piano 2012
Il motivo del cambiamento di comportamento è che nelle versioni precedenti SQL Server produceva un piano condiviso tra le esecuzioni con SET ROWCOUNT 0
(off) e SET ROWCOUNT N
. L'operatore di ordinamento era presente solo per garantire la semantica corretta nel caso in cui il piano fosse eseguito da una sessione con un ROWCOUNT
diverso da zero impostare. Il TOP
l'operatore alla sua sinistra è un ROWCOUNT TOP
.
SQL Server 2012 ora produce piani separati per i due casi, quindi non è necessario aggiungerli a ROWCOUNT 0
versione del piano.
Un ordinamento potrebbe ancora essere visualizzato nel piano nel 2012 se SELECT
ha un esplicito TOP
definito (diverso da TOP 100 PERCENT
) ma ciò non garantisce ancora l'ordine di inserimento effettivo delle righe, il piano potrebbe quindi avere un altro ordinamento dopo il TOP N
è stabilito per ottenere le righe nell'ordine dell'indice cluster, ad esempio.
Per l'esempio nella tua domanda, regolerei semplicemente il codice chiamante per specificare ORDER BY name
se è quello che richiede.
Riguardo al tuo sort_id
idea da Ordinazione delle garanzie in SQL Server
è garantito quando si inserisce in una tabella con IDENTITY
che l'ordine a cui vengono assegnati sarà come da ORDER BY
quindi potresti fare anche
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
ma dovresti comunque ordinare tramite sort_id
nelle tue query di selezione in quanto non esiste un ordinamento garantito senza quello (forse questo sort_id
potrebbe essere utile nel caso in cui le colonne originali utilizzate per l'ordinamento non vengano copiate nella variabile della tabella)