Exécutez le code SQL suivant en 2008 et 2012. Une fois exécuté en 2008, le résultat renvoyé se trouve dans le bon ordre de tri. En 2012, l'ordre de tri n'est pas retenu.
Est-ce un changement connu? Existe-t-il une solution pour 2012 afin de conserver l'ordre de tri?
CREATE TABLE #MyTable(Name VARCHAR(50), SortOrder INT)
INSERT INTO #MyTable SELECT 'b', 2 UNION ALL SELECT 'c', 3 UNION ALL SELECT 'a', 1 UNION ALL SELECT 'e', 5 UNION ALL SELECT 'd', 4
SELECT * INTO #Result FROM #MyTable ORDER BY SortOrder
SELECT * FROM #Result
DROP TABLE #MyTable
DROP TABLE #Result
Comment savoir quelle est la commande dans une table en utilisant select * from #result
? Il n'y a aucune garantie quant à l'ordre dans une requête select
.
Cependant, les résultats sont différents sur SQL Fiddle. Si vous voulez vous assurer que les résultats sont identiques, ajoutez une clé primaire. Alors l'ordre d'insertion est garanti:
CREATE TABLE MyTable(Name VARCHAR(50), SortOrder INT)
INSERT INTO MyTable SELECT 'b', 2 UNION ALL SELECT 'c', 3 UNION ALL SELECT 'a', 1 UNION ALL SELECT 'e', 5 UNION ALL SELECT 'd', 4
select top 0 * into result from MyTable;
alter table Result add id int identity(1, 1) primary key;
insert into Result(name, sortorder)
SELECT * FROM MyTable
ORDER BY SortOrder;
J'ai encore horreur de faire select * from Result
après cela. Mais oui, il les renvoie dans le bon ordre dans SQL Server 2008 et 2012. Non seulement cela, mais comme SQL Server garantit que les clés primaires sont insérées dans le bon ordre, il est même garanti que les enregistrements sont dans le bon ordre. ce cas.
MAIS . . . le fait que les enregistrements soient dans un ordre particulier sur les pages ne signifie pas qu'ils seront récupérés dans cet ordre sans clause order by
.
Lors de l'utilisation de ORDER BY
avec une INSERT
, il n'a jamais été garanti de faire quoi que ce soit autre que le contrôle de l'ordre de la colonne identity si présent.
Avant SQL Server 2012, l'optimiseur produisait toujours un plan comme si une colonne d'identité existait et semble donc s'ordonner correctement. SQL Server 2012 n'assume pas correctement une colonne d'identité et ne commande que si la table a réellement une colonne d'identité.
Vous pouvez donc résoudre ce problème en ajoutant une colonne Identity à votre table de résultats temporaire.
Cependant, vous devriez vraiment juste ajouter une clause ORDER BY
à votre instruction SELECT
? Les instructions SELECT
sans ORDER BY
n'ont jamais été garanties de renvoyer les résultats dans un ordre spécifique. Ajoutez toujours la clause ORDER BY
pour vous assurer de recevoir les résultats comme vous le souhaitez.
Tout d’abord, merci pour l’explication, cela nous a beaucoup aidé. Le problème de la définition d’une variable de table ou de la création d’une table temporaire, c’est que vous devez la définir, et si vous allez le définir, vous pouvez aussi bien insérer l’insert de la bonne manière:
INSERT INTO #Result (col1, col2...)
SELECT Col1, Col2... FROM #MyTable....
Dans mon cas, ORDER BY dans INSERT était dynamique et lorsque j'ai appelé "SELECT * FROM #Result", ORDER BY était inconnu. Ma solution a été d’ajouter une colonne ROW_NUMBER que je pouvais coder en dur dans SELECT en même temps que les données. Oui, je dois encore inclure un ORDER BY, mais au moins c'est statique. Voici ce que j'ai fait:
--Insert
SELECT ROW_NUMBER() OVER (ORDER BY T.SortOrder ASC) AS RowNum, T.*
INTO #Result
FROM (SELECT * FROM #MyTable ...) AS T;
--Get data out
SELECT * FROM #Result ORDER BY RowNum;
J'espère que cela t'aides.
Solution: Vous pouvez ajouter un SET ROWCOUNT
avant ce type de requête, puis le remettre à zéro après pour le réinitialiser. Cela fonctionne. Cela forcera SQL à conserver l'ordre dans votre requête.
SET ROWCOUNT 1000000000
CREATE TABLE #MyTable(Name VARCHAR(50), SortOrder INT)
INSERT INTO #MyTable SELECT 'b', 2 UNION ALL SELECT 'c', 3 UNION ALL SELECT 'a', 1 UNION ALL SELECT 'e', 5 UNION ALL SELECT 'd', 4
SELECT * INTO #Result FROM #MyTable ORDER BY SortOrder
SELECT * FROM #Result
SET ROWCOUNT 0
DROP TABLE #MyTable
DROP TABLE #Result
Si vous avez différents résultats de tri lorsque vous interrogez chaque base de données, votre classement est probablement différent entre les deux.
Essayez explicitement en définissant le classement dans votre requête et voyez si vos résultats sont renvoyés dans le même ordre dans les deux bases de données, par exemple.
SELECT * FROM #Result ORDER BY C1 COLLATE Latin1_General_CS_AS
Vous devez créer ROW_NUMBER () ordre par colonne que vous souhaitez commander. Ordre directement dans la sélection, est ignoré lors de l’insertion.
CREATE TABLE #MyTable (Nom VARCHAR (50), SortOrder INT) INSÉRER DANS #MyTable SÉLECTIONNER 'b', 2 UNION TOUT SELECTIONNER 'c', 3 UNION TOUT SELECTIONNER 'a', 1 TUNION TOUT SELECTIONNER 'e', 5 UNION TOUT SELECTIONNER 'd', 4 SELECT Nom, ROW_NUMBER () OVER (ORDER BY MyTable.SortOrder) AS SortOrder IN #Résultat DE #MyTable AS MyTable ORDER BY SortOrder SELECT * FROM #Result TABLEAU D'ALIMENTATION #MyTable TABLEAU D'ALIMENTATION #Résultat