Nous passons de SQL Server 2008 à SQL Server 2012 et remarquons immédiatement que toutes nos fonctions de table ne fournissent plus leur contenu de table temporaire dans l'ordre correct.
CODE:
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**
Dans SQL Server 2008, cette fonction renvoie les clients sortingés par nom. Dans SQL Server 2012, il renvoie la table non sortingée. La "command par" est ignorée dans SQL 2012.
Devons-nous réécrire toutes les fonctions pour inclure un sort_id
puis les sortinger quand ils sont appelés dans l'application principale ou y a-t-il une solution facile?
Il y avait deux choses qui ne marchaient pas avec votre approche originale.
ORDER BY
sur l' INSERT ... SELECT ... ORDER BY
serait l'ordre dans lequel les lignes étaient réellement insérées. SELECT
sans un ORDER BY
returnnera les lignes dans un ordre particulier tel que l'ordre d'insertion de toute façon. En 2012, il semble que le comportement a changé par rapport à l'élément 1. Il ignore maintenant généralement ORDER BY
sur l' SELECT
qui est la source d'un INSERT
DECLARE @T TABLE(number int) INSERT INTO @T SELECT number FROM master..spt_values ORDER BY name
La raison du changement de comportement est que dans les versions précédentes, SQL Server produisait un plan partagé entre les exécutions avec SET ROWCOUNT 0
(désactivé) et SET ROWCOUNT N
L'opérateur de sorting était uniquement là pour garantir la sémantique correcte dans le cas où le plan était exécuté par une session avec un set ROWCOUNT
non nul. L'opérateur TOP
à gauche de celui-ci est un ROWCOUNT TOP
.
SQL Server 2012 produit maintenant des plans distincts pour les deux cas, il n'est donc pas nécessaire de les append à la version ROWCOUNT 0
du plan.
Un sorting 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 pourrait alors avoir un autre sorting après que le TOP N
est établi pour get les lignes dans l'ordre de l'index clusterisé par exemple.
Pour l'exemple de votre question, je voudrais simplement ajuster le code appelant pour spécifier le ORDER BY name
si c'est ce dont il a besoin.
En ce qui concerne votre idée sort_id
des garanties de command dans SQL Server, il est garanti lors de l'insertion dans une table avec IDENTITY
que la command qui leur est allouée sera sort_id
à la command ORDER BY
, vous pouvez également 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 devrez toujours order par sort_id
dans vos requêtes de sélection car il n'y a pas de command garantie sans cela (peut-être que cette approche sort_id
pourrait être utile dans le cas où les colonnes d'origine utilisées pour la command ne sont pas copiées dans la variable table)
append une colonne nommée rowno à la table @Customer
INSERT INTO @Customer SELECT ROW_NUMBER()over(order by Name)rowno,Customer_ID, Name, CASE WHEN Expiry_Date < GETDATE() then 1 WHEN Expired = 1 then 1 ELSE 0 END from Customer