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
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
句なしでその順序でレコードが取得されるとは限りません。
ORDER BY
をINSERT
と一緒に使用する場合、identity column(存在する場合)の順序を制御する以外のことを行うことは保証されていません。
SQL Server 2012より前は、オプティマイザーは常にID列が存在するかのようにプランを作成していたため、正しく順序付けられているように見えました。 SQL Server 2012は、ID列が存在することを正しく想定せず、テーブルに実際にID列がある場合にのみ注文します。
したがって、一時結果テーブルにIdentity列を追加することで、この問題を解決できます。
ただし、実際にはSELECT
ステートメントにORDER BY
句を追加する必要がありますか? ORDER BY
のないSELECT
ステートメントは、特定の順序で結果を返すことが保証されていません。期待どおりの結果が得られるように、常にORDER BY
句を追加してください。
まず、説明してくれた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;
お役に立てれば。
回避策:このタイプのクエリの前に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
各データベースにクエリを実行するときに並べ替えられた結果が異なる場合、照合順序はおそらく 2つの間で異なります。
明示的にクエリで照合順序を設定し、結果が両方のデータベースで同じ順序で返されるかどうかを確認してください。
SELECT * FROM #Result ORDER BY C1 COLLATE Latin1_General_CS_AS
注文する列ごとに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