W twoim pierwotnym podejściu były dwie rzeczy niewłaściwe.
- Przy wstawianiu do tabeli nigdy nie było zagwarantowane, że
ORDER BY
naINSERT ... SELECT ... ORDER BY
to kolejność, w jakiej wiersze zostały faktycznie wstawione. - Po wybraniu z niego SQL Server nie gwarantuje, że
SELECT
bezORDER BY
i tak zwróci wiersze w dowolnej kolejności, na przykład w kolejności reklamowej.
W 2012 wygląda na to, że zachowanie zmieniło się w stosunku do pozycji 1. Teraz generalnie ignoruje ORDER BY
na SELECT
instrukcja będąca źródłem INSERT
DECLARE @T TABLE(number int)
INSERT INTO @T
SELECT number
FROM master..spt_values
ORDER BY name
Plan 2008
Plan 2012
Powodem zmiany zachowania jest to, że w poprzednich wersjach SQL Server generował jeden plan, który był współdzielony między wykonaniami z SET ROWCOUNT 0
(off) i SET ROWCOUNT N
. Operator sortowania był tam tylko po to, aby zapewnić poprawną semantykę w przypadku, gdy plan został uruchomiony przez sesję z niezerowym ROWCOUNT
ustawić. TOP
operator po lewej stronie to ROWCOUNT TOP
.
SQL Server 2012 tworzy teraz oddzielne plany dla dwóch przypadków, więc nie ma potrzeby dodawania ich do ROWCOUNT 0
wersja planu.
Sortowanie może nadal pojawiać się w planie w 2012 roku, jeśli SELECT
ma wyraźny TOP
zdefiniowane (inne niż TOP 100 PERCENT
), ale nadal nie gwarantuje to rzeczywistej kolejności wstawiania wierszy, plan może mieć wtedy inne sortowanie po TOP N
jest ustanowiona, aby na przykład uporządkować wiersze w kolejności indeksu klastrowego.
Na przykład w twoim pytaniu po prostu dostosowałbym kod wywołujący, aby określić ORDER BY name
jeśli tego wymaga.
Odnośnie Twojego sort_id
pomysł Gwarancje zamawiania w SQL Server
jest to gwarantowane przy wstawianiu do tabeli z IDENTITY
że kolejność ich przydzielania będzie zgodna z ORDER BY
więc możesz też zrobić
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
ale nadal musisz zamawiać według sort_id
w zapytaniach wybierających, ponieważ bez tego nie ma gwarantowanej kolejności (być może ten sort_id
podejście może być przydatne w przypadku, gdy oryginalne kolumny użyte do zamówienia nie są kopiowane do zmiennej tabeli)