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

多数の行を持つ既存のデータベース テーブルに ID 列を追加する方法

    全体的なプロセスは、全体的なロック オーバーヘッドが大きくなるとおそらくかなり遅くなりますが、トランザクション ログのサイズだけを気にする場合は、次の方法を試すことができます。

    <オール>
  1. null 許容整数非 ID 列を追加します (メタデータのみの変更)。
  2. バッチ内の一意の連続した整数でこれを更新するコードを記述します。これにより、個々のトランザクションのサイズが縮小され、ログのサイズが抑えられます (単純な復旧モデルを想定)。以下の私のコードはこれを 100 個のバッチで実行します。願わくば、既存の PK を利用して、終了に向かってますます時間がかかる繰り返しのスキャンではなく、中断したところから再開できることを願っています。
  3. ALTER TABLE ... ALTER COLUMN を使用 列を NOT NULL としてマークする .これには、変更を検証するためにテーブル全体をロックしてスキャンする必要がありますが、多くのログは必要ありません。
  4. ALTER TABLE ... SWITCH を使用します 列を ID 列にします。これはメタデータのみの変更です。
  5. 以下のコード例

    /*Set up test table with just one column*/
    
    CREATE TABLE table_1 ( original_column INT )
    INSERT  INTO table_1
            SELECT DISTINCT
                    number
            FROM    master..spt_values
    
    
    
    /*Step 1 */
    ALTER TABLE table_1 ADD id INT NULL
    
    
    
    /*Step 2 */
    DECLARE @Counter INT = 0 ,
        @PrevCounter INT = -1
    
    WHILE @PrevCounter <> @Counter 
        BEGIN
            SET @PrevCounter = @Counter;
            WITH    T AS ( SELECT TOP 100
                                    * ,
                                    ROW_NUMBER() OVER ( ORDER BY @@SPID )
                                    + @Counter AS new_id
                           FROM     table_1
                           WHERE    id IS NULL
                         )
                UPDATE  T
                SET     id = new_id
            SET @Counter = @Counter + @@ROWCOUNT
        END
    
    
    BEGIN TRY;
        BEGIN TRANSACTION ;
         /*Step 3 */
        ALTER TABLE table_1 ALTER COLUMN id INT NOT NULL
    
        /*Step 4 */
        DECLARE @TableScript NVARCHAR(MAX) = '
        CREATE TABLE dbo.Destination(
            original_column INT,
            id INT IDENTITY(' + CAST(@Counter + 1 AS VARCHAR) + ',1)
            )
    
            ALTER TABLE dbo.table_1 SWITCH TO dbo.Destination;
        '       
    
        EXEC(@TableScript)
    
    
        DROP TABLE table_1 ;
    
        EXECUTE sp_rename N'dbo.Destination', N'table_1', 'OBJECT' ;
    
    
        COMMIT TRANSACTION ;
    END TRY
    BEGIN CATCH
        IF XACT_STATE() <> 0 
            ROLLBACK TRANSACTION ;
        PRINT ERROR_MESSAGE() ;
    END CATCH ;
    


    1. MySQL ACOS()関数–数値のアークコサインを返します

    2. Postgres-欠測データのカウントが0の行を返す方法は?

    3. MySQLで日付間のギャップを表示する

    4. パスワードをデータベースに安全に保存する方法は?