web-dev-qa-db-ja.com

SELECT * INTOはSQLServer2008ではORDERBYを保持しますが、2012では保持しません

2008年と2012年に次のSQLを実行します。2008年に実行すると、返される結果は正しい並べ替え順序になります。 2012年には、ソート順は保持されません。

これは既知の変更ですか?ソート順を維持するための2012年の回避策はありますか?

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
10
Rivka

select * from #resultを使用して、テーブル内の順序をどのように判断できますか? selectクエリの順序については保証されません。

ただし、SQLFiddleでは結果が異なります。結果が同じであることを保証したい場合は、主キーを追加します。次に、挿入順序が保証されます。

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;

この後もselect * from Resultをするのは嫌いです。しかし、はい、SQL Server 2008と2012の両方で正しい順序でそれらを返します。それだけでなく、SQL Serverは主キーが正しい順序で挿入されることを保証するため、レコードは正しい順序であることが保証されます。この場合。

だが 。 。 。レコードがページ上で特定の順序になっているからといって、order by句なしでその順序でレコードが取得されるとは限りません。

17
Gordon Linoff

ORDER BYINSERTと一緒に使用する場合、identity column(存在する場合)の順序を制御する以外のことを行うことは保証されていません。

SQL Server 2012より前は、オプティマイザーは常にID列が存在するかのようにプランを作成していたため、正しく順序付けられているように見えました。 SQL Server 2012は、ID列が存在することを正しく想定せず、テーブルに実際にID列がある場合にのみ注文します。

したがって、一時結果テーブルにIdentity列を追加することで、この問題を解決できます。

ただし、実際にはSELECTステートメントにORDER BY句を追加する必要がありますか? ORDER BYのないSELECTステートメントは、特定の順序で結果を返すことが保証されていません。期待どおりの結果が得られるように、常にORDER BY句を追加してください。

9
sgeddes

まず、説明してくれたsgeddesに感謝します、それは大いに役立ちました。テーブル変数の定義または一時テーブルの作成については、それを定義する必要があります。それを定義する作業を行う場合は、正しい方法で挿入を行うことをお勧めします。

INSERT INTO #Result (col1, col2...)
SELECT Col1, Col2... FROM #MyTable....

私の場合、INSERTのORDER BYは動的であったため、「SELECT * FROM #Result」を呼び出したとき、ORDERBYは不明でした。私の解決策は、データを取得するときにSELECTにハードコーディングできるROW_NUMBER列を追加することでした。ええ、私はまだORDER BYを含める必要がありますが、少なくともそれは静的です。これが私がしたことです:

--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;

お役に立てれば。

2
Losbear

回避策:このタイプのクエリの前にSET ROWCOUNTを追加し、リセット後にゼロに戻した場合は機能します。これにより、SQLはクエリの順序を維持します。

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
0
patrick imbault

各データベースにクエリを実行するときに並べ替えられた結果が異なる場合、照合順序はおそらく 2つの間で異なります。

明示的にクエリで照合順序を設定し、結果が両方のデータベースで同じ順序で返されるかどうかを確認してください。

SELECT * FROM #Result ORDER BY C1 COLLATE Latin1_General_CS_AS
0
George Johnston

注文する列ごとにROW_NUMBER()を作成する必要があります。選択で直接並べ替えます。挿入が実行されると無視されます。

 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 Name、
 ROW_NUMBER()OVER(ORDER BY MyTable.SortOrder)AS SortOrder 
 INTO #Result 
 FROM #MyTable AS MyTable 
 ORDER BY SortOrder 
 
 SELECT * FROM #Result 
 
 DROP TABLE #MyTable 
 DROP TABLE #Result 
0
Snowww