SQL Server2008からSQLServer 2012に移行していると、すべてのテーブル値関数が、正しくソートされた順序で一時テーブルの内容を配信しなくなったことにすぐに気付きました。
コード:
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**
SQL Server 2008では、この関数は名前でソートされた顧客を返します。 SQL Server 2012では、並べ替えられていないテーブルを返します。 "order by"はSQL2012では無視されます。
すべての関数を書き直してsort_id
を含め、メインアプリケーションで呼び出されたときに並べ替える必要がありますか、それとも簡単な修正がありますか?
元のアプローチには2つの問題がありました。
ORDER BY
_の_INSERT ... SELECT ... ORDER BY
_が実際に行が挿入された順序であることが保証されることはありませんでした。ORDER BY
_のないSELECT
が挿入順序などの特定の順序で行を返すことを保証しません。2012年には、項目1に関して動作が変更されたように見えます。現在は通常、SELECT
のソースであるINSERT
ステートメントの_ORDER BY
_を無視します。
_DECLARE @T TABLE(number int)
INSERT INTO @T
SELECT number
FROM master..spt_values
ORDER BY name
_
動作が変更された理由は、以前のバージョンでは、SQL Serverが_SET ROWCOUNT 0
_(オフ)と_SET ROWCOUNT N
_の実行間で共有される1つのプランを作成したためです。ソート演算子は、プランがゼロ以外のROWCOUNT
セットのセッションによって実行された場合に正しいセマンティクスを保証するためにのみ存在していました。その左側のTOP
演算子は _ROWCOUNT TOP
_ です。
SQL Server 2012は、2つのケースに対して別々のプランを作成するようになったため、これらをプランの_ROWCOUNT 0
_バージョンに追加する必要はありません。
SELECT
に明示的なTOP
が定義されている場合(_TOP 100 PERCENT
_以外)、2012年のプランに並べ替えが表示される場合がありますが、これは行の実際の挿入順序を保証するものではありません。たとえば、行をクラスター化されたインデックスの順序にするために_TOP N
_が確立された後、プランは別の並べ替えを行う場合があります。
あなたの質問の例では、それが必要な場合は、呼び出しコードを調整して_ORDER BY name
_を指定します。
SQL Server での順序保証からの_sort_id
_アイデアに関しては、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
_アプローチは、順序付けに使用された元の列がない場合に役立つ可能性があります。 tはテーブル変数にコピーされます)
rownoという名前の列を@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