Il y avait deux choses qui n'allaient pas dans votre approche initiale.
- Lors de l'insertion dans le tableau, il n'a jamais été garanti que le
ORDER BYsurINSERT ... SELECT ... ORDER BYserait l'ordre dans lequel les lignes ont été réellement insérées. - En le sélectionnant, SQL Server ne garantit pas que
SELECTsansORDER BYrenverra les lignes dans n'importe quel ordre particulier tel que l'ordre d'insertion de toute façon.
En 2012, il semble que le comportement ait changé par rapport à l'élément 1. Il ignore maintenant généralement le ORDER BY sur le SELECT instruction qui est la source d'un INSERT
DECLARE @T TABLE(number int)
INSERT INTO @T
SELECT number
FROM master..spt_values
ORDER BY name
Plan 2008

Plan 2012

La raison du changement de comportement est que dans les versions précédentes, SQL Server produisait un plan qui était partagé entre les exécutions avec SET ROWCOUNT 0 (off) et SET ROWCOUNT N . L'opérateur de tri n'était là que pour garantir la sémantique correcte dans le cas où le plan était exécuté par une session avec un ROWCOUNT non nul Positionner. Le TOP l'opérateur à sa gauche est un ROWCOUNT TOP
.
SQL Server 2012 produit désormais des plans distincts pour les deux cas, il n'est donc pas nécessaire de les ajouter au ROWCOUNT 0 version du plan.
Un tri peut encore apparaître dans le plan en 2012 si le SELECT a un TOP explicite défini (autre que TOP 100 PERCENT ) mais cela ne garantit toujours pas l'ordre d'insertion réel des lignes, le plan peut alors avoir un autre tri après le TOP N est établi pour obtenir les lignes dans l'ordre de l'index clusterisé par exemple.
Pour l'exemple de votre question, je voudrais simplement ajuster le code d'appel pour spécifier ORDER BY name si c'est ce qu'il faut.
Concernant votre sort_id idée de Garanties de commande dans SQL Server
il est garanti lors de l'insertion dans une table avec IDENTITY que l'ordre qui leur est attribué sera conforme au ORDER BY donc tu peux aussi faire
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
mais vous auriez toujours besoin de commander par le sort_id dans vos requêtes de sélection car il n'y a pas de commande garantie sans cela (peut-être ce sort_id approche peut être utile dans le cas où les colonnes d'origine utilisées pour le tri ne sont pas copiées dans la variable de table)