Havia duas coisas erradas com sua abordagem original.
- Ao inserir na tabela, nunca foi garantido que o
ORDER BY
noINSERT ... SELECT ... ORDER BY
seria a ordem em que as linhas foram realmente inseridas. - Ao selecionar a partir dele, o SQL Server não garante que
SELECT
sem umORDER BY
retornará as linhas em qualquer ordem específica, como ordem de inserção.
Em 2012, parece que o comportamento mudou em relação ao item 1. Agora geralmente ignora o
ORDER BY
no SELECT
declaração que é a fonte para um INSERT
DECLARE @T TABLE(number int)
INSERT INTO @T
SELECT number
FROM master..spt_values
ORDER BY name
Plano 2008
Plano 2012
O motivo da mudança de comportamento é que nas versões anteriores o SQL Server produzia um plano que era compartilhado entre as execuções com
SET ROWCOUNT 0
(desligado) e SET ROWCOUNT N
. O operador de classificação estava lá apenas para garantir a semântica correta caso o plano fosse executado por uma sessão com um ROWCOUNT
diferente de zero definir. O TOP
operador à esquerda dele é um ROWCOUNT TOP
. O SQL Server 2012 agora produz planos separados para os dois casos, portanto, não há necessidade de adicioná-los ao
ROWCOUNT 0
versão do plano. Uma classificação ainda pode aparecer no plano em 2012 se o
SELECT
tem um TOP
explícito definido (diferente de TOP 100 PERCENT
), mas isso ainda não garante a ordem de inserção real das linhas, o plano pode ter outra classificação após o TOP N
é estabelecido para obter as linhas em ordem de índice clusterizado, por exemplo. Para o exemplo em sua pergunta, eu apenas ajustaria o código de chamada para especificar
ORDER BY name
se é isso que requer. Em relação ao seu
sort_id
ideia de Garantias de pedidos no SQL Server
é garantido ao inserir em uma tabela com IDENTITY
que a ordem em que eles são alocados será de acordo com o ORDER BY
então você também pode fazer 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
mas você ainda precisaria fazer o pedido pelo
sort_id
em suas consultas de seleção, pois não há pedidos garantidos sem isso (talvez este sort_id
abordagem pode ser útil no caso em que as colunas originais usadas para ordenação não estão sendo copiadas para a variável da tabela)