Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Функция с таблична стойност - Подреждане по се игнорира в изхода

Имаше две нередни неща в първоначалния ви подход.

  1. При вмъкване в таблицата никога не е гарантирано, че ORDER BY на INSERT ... SELECT ... ORDER BY ще бъде редът, в който редовете са действително вмъкнати.
  2. При избиране от него 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 подходът може да е полезен в случай, че оригиналните колони, използвани за подреждане, не се копират в променливата на таблицата)



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Вземете някой от записите в дублирани записи

  2. Хеширане на парола в SQL

  3. Как да получа запис с Max(date) и след това да сравня стойностите, за да получа резултат

  4. Как да направите заявка за ролите на текущия потребител

  5. Как да предотвратите едновременното изпълнение на задания на Sql сървър