元のアプローチには 2 つの問題がありました。
<オール>ORDER BY
が保証されていませんでした。 INSERT ... SELECT ... ORDER BY
で 行が実際に挿入された順序になります。SELECT
を保証しません。 ORDER BY
なし とにかく、挿入順序などの特定の順序で行を返します。
2012 年には、項目 1 に関して動作が変更されたように見えます。現在は、通常、ORDER BY
を無視します。 SELECT
で INSERT
のソースであるステートメント
DECLARE @T TABLE(number int)
INSERT INTO @T
SELECT number
FROM master..spt_values
ORDER BY name
2008 年計画
2012 年計画
動作が変更された理由は、以前のバージョンの SQL Server では、SET ROWCOUNT 0
を使用して実行間で共有される 1 つの計画が生成されたためです。 (オフ) および SET ROWCOUNT N
.ソート演算子は、ゼロ以外の ROWCOUNT
を持つセッションによってプランが実行された場合に正しいセマンティクスを保証するためだけにありました 設定。 TOP
その左側の演算子は ROWCOUNT TOP
.
SQL Server 2012 は 2 つのケースに対して個別の計画を作成するようになったため、これらを ROWCOUNT 0
に追加する必要はありません。 計画のバージョン。
SELECT
が 明示的な TOP
があります 定義済み (TOP 100 PERCENT
以外) ) しかし、これでも行の実際の挿入順序は保証されません。その場合、プランは TOP N
の後に別の並べ替えを行う可能性があります。 たとえば、行をクラスター化されたインデックスの順序にするために確立されます。
あなたの質問の例では、呼び出しコードを調整して ORDER BY name
を指定するだけです それが必要な場合。
sort_id
について SQL Server での順序保証
からのアイデア IDENTITY
でテーブルに挿入すると保証されます これらが割り当てられる順序は ORDER BY
に従っていること あなたもできるように
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
sort_id
で並べ替える必要があります それなしでは保証された順序がないため、選択クエリで(おそらくこの sort_id
このアプローチは、順序付けに使用される元の列がテーブル変数にコピーされていない場合に役立ちます)