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

別の列のコンテキストでの SQL Server の一意の自動インクリメント列

    このタイプの列はネイティブでサポートされていませんが、トリガーを使用して実装できます:

    CREATE TRIGGER tr_MyTable_Number
    ON MyTable
    INSTEAD OF INSERT
    AS
    
    SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
    
    BEGIN TRAN;
    
    WITH MaxNumbers_CTE AS
    (
        SELECT ParentEntityID, MAX(Number) AS Number
        FROM MyTable
        WHERE ParentEntityID IN (SELECT ParentEntityID FROM inserted)
    )
    INSERT MyTable (ParentEntityID, Number)
        SELECT
            i.ParentEntityID,
            ROW_NUMBER() OVER
            (
                PARTITION BY i.ParentEntityID
                ORDER BY (SELECT 1)
            ) + ISNULL(m.Number, 0) AS Number
        FROM inserted i
        LEFT JOIN MaxNumbers_CTE m
            ON m.ParentEntityID = i.ParentEntityID
    
    COMMIT
    

    テストしていませんが、うまくいくと確信しています。主キーがある場合は、これを AFTER として実装することもできます トリガー (INSTEAD OF の使用は嫌いです) トリガー、6 か月後に変更する必要があるときに理解するのが難しくなります)。

    ここで何が起こっているかを説明すると:

      <リ>

      SERIALIZABLE 最も厳格な分離モードです。一度に 1 つのデータベース トランザクションのみがこれらのステートメントを実行できることが保証されます。これは、この「シーケンス」の整合性を保証するために必要です。これはトランザクション全体を不可逆的に昇格させるため、長時間実行されるトランザクション内でこれを使用したくないことに注意してください。

      <リ>

      CTE は、各親 ID で既に使用されている最大数を取得します。

      <リ>

      ROW_NUMBER 親 ID ごとに一意のシーケンスを生成します (PARTITION BY ) 番号 1 から開始します。新しいシーケンスを取得する前の最大値がある場合は、これを以前の最大値に追加します。

    また、一度に 1 つの新しい子エンティティを挿入するだけでよい場合は、トリガーを使用する代わりに、ストアド プロシージャを介してこれらの操作を処理する方がよいことにも言及する必要があります。これにより、パフォーマンスが確実に向上します。 . hierarchyid で現在行われている方法は次のとおりです。 SQL '08 の列。



    1. MySQLWorkbenchで図からスクリプトを生成する方法

    2. GoogleBigQueryODBCドライバー

    3. 複数のスレッドが制約されたセットで重複した更新を引き起こす可能性がありますか?

    4. MySQL-クエリの実行に許可される最大時間を制限できますか?