Había dos cosas mal con su enfoque original.
- Al insertar en la tabla, nunca se garantizó que el
ORDER BY
enINSERT ... SELECT ... ORDER BY
sería el orden en que se insertaron realmente las filas. - Al seleccionarlo, SQL Server no garantiza que
SELECT
sinORDER BY
devolverá las filas en cualquier orden en particular, como el orden de inserción de todos modos.
En 2012 parece que el comportamiento ha cambiado con respecto al elemento 1. Ahora generalmente ignora el ORDER BY
en el SELECT
declaración que es la fuente de un INSERT
DECLARE @T TABLE(number int)
INSERT INTO @T
SELECT number
FROM master..spt_values
ORDER BY name
Plan 2008
Plan 2012
El motivo del cambio de comportamiento es que en versiones anteriores SQL Server producía un plan que se compartía entre ejecuciones con SET ROWCOUNT 0
(apagado) y SET ROWCOUNT N
. El operador de clasificación solo estaba allí para garantizar la semántica correcta en caso de que el plan fuera ejecutado por una sesión con un ROWCOUNT
distinto de cero establecer. El TOP
el operador a la izquierda es un ROWCOUNT TOP
.
SQL Server 2012 ahora produce planes separados para los dos casos, por lo que no es necesario agregarlos a ROWCOUNT 0
versión del plan.
Una clasificación aún puede aparecer en el plan en 2012 si SELECT
tiene un TOP
explícito definido (que no sea TOP 100 PERCENT
) pero esto aún no garantiza el orden de inserción real de las filas, el plan podría tener otro tipo después del TOP N
se establece para obtener las filas en orden de índice agrupado, por ejemplo.
Para el ejemplo de su pregunta, simplemente ajustaría el código de llamada para especificar ORDER BY name
si eso es lo que requiere.
Con respecto a su sort_id
idea de Garantías de pedido en SQL Server
se garantiza al insertar en una tabla con IDENTITY
que el orden en que se asignan será según el ORDER BY
así que también podrías hacer
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
pero aún tendría que ordenar por el sort_id
en sus consultas de selección ya que no hay orden garantizado sin eso (quizás este sort_id
El enfoque puede ser útil en el caso de que las columnas originales utilizadas para ordenar no se copien en la variable de la tabla)