sql >> データベース >  >> RDS >> Sqlserver

テーブル値関数 - 出力では Order by は無視されます

    元のアプローチには 2 つの問題がありました。

    <オール>
  1. テーブルへの挿入時に、ORDER BY が保証されていませんでした。 INSERT ... SELECT ... ORDER BY で 行が実際に挿入された順序になります。
  2. そこから選択する場合、SQL Server は SELECT を保証しません。 ORDER BY なし とにかく、挿入順序などの特定の順序で行を返します。
  3. 2012 年には、項目 1 に関して動作が変更されたように見えます。現在は、通常、ORDER BY を無視します。 SELECTINSERT のソースであるステートメント

    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 このアプローチは、順序付けに使用される元の列がテーブル変数にコピーされていない場合に役立ちます)



    1. PostreSQLでのINSERTとトランザクションのシリアル化

    2. エラー:文字46のスキーマuser1_gmail_comの権限が拒否されました

    3. 1つのphpページで2つのテーブルを使用する(mysql)

    4. 配列をmysqlに保存する方法は?