Имаше две нередни неща в първоначалния ви подход.
- При вмъкване в таблицата никога не е гарантирано, че
ORDER BY
наINSERT ... SELECT ... ORDER BY
ще бъде редът, в който редовете са действително вмъкнати. - При избиране от него SQL Server не гарантира, че
SELECT
безORDER BY
така или иначе ще върне редовете във всеки определен ред, като например ред за вмъкване.
През 2012 г. изглежда, че поведението се е променило по отношение на елемент 1. Сега обикновено игнорира ORDER BY
на SELECT
израз, който е източникът за INSERT
DECLARE @T TABLE(number int)
INSERT INTO @T
SELECT number
FROM master..spt_values
ORDER BY name
План за 2008 г.
План за 2012 г.
Причината за промяната на поведението е, че в предишните версии SQL Server създава един план, който се споделя между изпълненията с SET ROWCOUNT 0
(изключено) и SET ROWCOUNT N
. Операторът за сортиране беше там само за да осигури правилната семантика в случай, че планът се изпълнява от сесия с ненулев ROWCOUNT
комплект. TOP
оператор вляво от него е ROWCOUNT TOP
.
SQL Server 2012 вече създава отделни планове за двата случая, така че няма нужда да ги добавяте към ROWCOUNT 0
версия на плана.
Сортиране все още може да се появи в плана през 2012 г., ако SELECT
има изричен TOP
дефинирани (различни от TOP 100 PERCENT
), но това все още не гарантира действителния ред на вмъкване на редове, тогава планът може да има друго сортиране след TOP N
е установен, за да приведе редовете в клъстериран индексен ред например.
За примера във вашия въпрос просто бих коригирал кода за повикване, за да посочи ORDER BY name
ако това се изисква.
Относно вашия sort_id
идея от Гаранции за поръчки в SQL Server
то е гарантирано при вмъкване в таблица с IDENTITY
че редът, в който се разпределят, ще бъде според ORDER BY
така че можете също да направите
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
но все пак ще трябва да поръчате по sort_id
във вашите заявки за избор, тъй като няма гарантирано подреждане без това (може би този sort_id
подходът може да е полезен в случай, че оригиналните колони, използвани за подреждане, не се копират в променливата на таблицата)