SQL ServerでID列を更新する方法


194

SQL Serverデータベースがあり、大きな数字で始まったため、ID列を変更したい 10010別のテーブルに関連しているためです。現在200レコードあり、レコードが増える前にこの問題を修正したいと思います。

この列を変更またはリセットする最良の方法は何ですか?

回答:


269

ID列を更新できません。

SQL Serverでは、更新ステートメントを使用して他の列で実行できることとは異なり、ID列を更新できません。

同様の要件を達成するためのいくつかの代替策がありますが。

  • Identity列の値を新しいレコード用に更新する必要がある場合

テーブルの現在のID値をチェックし、必要に応じてID値を変更するDBCC CHECKIDENT 使用します。

DBCC CHECKIDENT('tableName', RESEED, NEW_RESEED_VALUE)
  • Identity列の値を既存のレコードに対して更新する必要がある場合

IDENTITY_INSERT 使用すると、明示的な値をテーブルのID列に挿入できます。

SET IDENTITY_INSERT YourTable {ON|OFF}

例:

-- Set Identity insert on so that value can be inserted into this column
SET IDENTITY_INSERT YourTable ON
GO
-- Insert the record which you want to update with new value in the identity column
INSERT INTO YourTable(IdentityCol, otherCol) VALUES(13,'myValue')
GO
-- Delete the old row of which you have inserted a copy (above) (make sure about FK's)
DELETE FROM YourTable WHERE ID=3
GO
--Now set the idenetity_insert OFF to back to the previous track
SET IDENTITY_INSERT YourTable OFF

6
DBCC次の新しいレコードをリセットしますが、ここで既存のレコードを変更します。
Abdulsalam Elsharif 2013年

例を挙げていただけますか?
Abdulsalam Elsharif 2013年

38
@sachinこれは手動で挿入する既存のIDENTITYを更新しません
Phill Greggan '26年

3
@PhillGregganはい、これはこれを達成するための最良の解決策です。通常の列を更新するときに、ID列を更新することはできません。
Sachin

17
この受け入れられた回答は、ID列(例:)を更新する方法である質問には答えませんUPDATE YourTable SET IdentityCol = 13SET IDENTITY_INSERT YourTable ONINSERTのみを許可し、UPDATEは許可しません。
Ian Boyd

61

あなたの質問が正しいなら、あなたは次のようなことをしたいです

update table
set identity_column_name = some value

簡単に言うと、foreign key関連付けられている可能性があるため、使用することはお勧めできません。

しかし、これはそれを行うための手順ですback-up、テーブルを取ってください

手順1-テーブルのデザインビューを選択する

ここに画像の説明を入力してください

手順2-ID列をオフにする

ここに画像の説明を入力してください

これでupdateクエリを使用できます。

次にredo、ステップ1とステップ2とID列をオンにします

参照


1
私はこのテーブルに関連する別のテーブルを持っていますが、私はそれを行うことができません
Abdulsalam Elsharif 2013年

4
したがって、ステートメントはお勧めできません :)
Luv

3
@AbdusalamElsherifしかし、ID列を変更する方法を尋ねました。
パパラッツォ2013年

@luv少なくとも、質問された質問に回答しました
Phill Greggan

この手順を使用して、開発データベースにIDを設定します。とにかくそれをさせてくれるコマンドがあればいいのですが、これはうまくいきます。
ジェフデイビス

56

必要がある

set identity_insert YourTable ON

次に、行を削除して、別のIDで再挿入します。

挿入が完了したら、identity_insertをオフにすることを忘れないでください。

set identity_insert YourTable OFF

これは、列のIDをオフにするよりもはるかに簡単で安全です。
プロテクター1

これは安全で、少数のレコードに対しては簡単ですが、質問に適切に回答しません。IDをオフにすると、より危険で、時には不可能になりますが、ID列を更新できます。
マシューハドソン

18
--before running this make sure Foreign key constraints have been removed that reference the ID. 

--set table to allow identity to be inserted
SET IDENTITY_INSERT yourTable ON;
GO
--insert everything into a temp table
SELECT * 
INTO #tmpYourTable
FROM yourTable

--clear your table
DELETE FROM yourTable
--insert back all the values with the updated ID column
INSERT INTO yourTable (IDCol, OtherCols)
SELECT ID+1 as updatedID --put any other update logic to the ID here
, OtherCols FROM #tmpYourTable
--drop the temp table
DROP TABLE #tmpYourTable
--put identity back to normal
SET IDENTITY_INSERT yourTable OFF;
GO

1
テーブルが非常に大きい場合は、パフォーマンスに関するヒントとして、テーブルで削除を実行する代わりに、Truncate Table yourTableを実行します。瞬時です。ただし、ログに記録されないため、truncateを使用して折り返すことはできません。
kuklei 2017年


5

ID列のない新しいテーブルにテーブルをコピーします。

    select columns into newtable from yourtable

ID列を新しいシードでnewtableに追加し、それを主キーにします

    ALTER TABLE tableName ADD id MEDIUMINT NOT NULL AUTO_INCREMENT KEY

3
DBCC CHECKIDENT(table_name, RESEED, value)

table_name =リセットしたいテーブルに値を与える

値= 0の初期値、ID列を1で開始


3
SET IDENTITY_INSERT dbo.TableName ON
INSERT INTO dbo.TableName 
(
    TableId, ColumnName1, ColumnName2, ColumnName3
)
VALUES
(
    TableId_Value, ColumnName1_Value, ColumnName2_Value, ColumnName3_Value
)

SET IDENTITY_INSERT dbo.TableName OFF

Identity_Insertを使用するときは、列名を含めることを忘れないでください。SQLでは、列名を指定しないと挿入できないためです。



1
ALTER TABLE tablename add newcolumn int
update tablename set newcolumn=existingcolumnname
ALTER TABLE tablename DROP COLUMN existingcolumnname;
EXEC sp_RENAME 'tablename.oldcolumn' , 'newcolumnname', 'COLUMN'
update tablename set newcolumnname=value where condition

ただし、上記のコードは、主キーと外部キーの関係がない場合にのみ機能します


1

コマンドビルダーを使用したC#プログラマ向けの完全なソリューション

まず第一に、あなたはこの事実を知る必要があります:

  • いずれの場合も、ID列を変更することはできないため、行を削除して、新しいIDで再度追加する必要があります。
  • 列からIDプロパティを削除することはできません(列から削除する必要があります)
  • .netのカスタムコマンドビルダーは常にID列をスキップするため、この目的で使用することはできません。

だから、それを知ったら、あなたは何をしなければならないかです。独自のSQL挿入ステートメントをプログラムするか、独自の挿入コマンドビルダーをプログラムします。または、私がプログラムしたこの1つを使用します。DataTableを指定すると、SQL挿入スクリプトを生成します。

public static string BuildInsertSQLText ( DataTable table )
{
    StringBuilder sql = new StringBuilder(1000,5000000);
    StringBuilder values = new StringBuilder ( "VALUES (" );
    bool bFirst = true;
    bool bIdentity = false;
    string identityType = null;

    foreach(DataRow myRow in table.Rows) 
    {
        sql.Append( "\r\nINSERT INTO " + table.TableName + " (" );

        foreach ( DataColumn column in table.Columns )
        {
            if ( column.AutoIncrement )
            {
                bIdentity = true;

                switch ( column.DataType.Name )
                {
                    case "Int16":
                        identityType = "smallint";
                        break;
                    case "SByte":
                        identityType = "tinyint";
                        break;
                    case "Int64":
                        identityType = "bigint";
                        break;
                    case "Decimal":
                        identityType = "decimal";
                        break;
                    default:
                        identityType = "int";
                        break;
                }
            }
            else
            {
                if ( bFirst )
                    bFirst = false;
                else
                {
                    sql.Append ( ", " );
                    values.Append ( ", " );
                }
                sql.Append ("[");
                sql.Append ( column.ColumnName );
                sql.Append ("]");

                //values.Append (myRow[column.ColumnName].ToString() );

                if (myRow[column.ColumnName].ToString() == "True")
                    values.Append("1");
                else if (myRow[column.ColumnName].ToString() == "False")
                    values.Append("0");
                else if(myRow[column.ColumnName] == System.DBNull.Value)    
                    values.Append ("NULL");
                else if(column.DataType.ToString().Equals("System.String"))
                {
                    values.Append("'"+myRow[column.ColumnName].ToString()+"'");
                }
                else
                    values.Append (myRow[column.ColumnName].ToString());
                    //values.Append (column.DataType.ToString() );
            }
        }
        sql.Append ( ") " );
        sql.Append ( values.ToString () );
        sql.Append ( ")" );

        if ( bIdentity )
        {
            sql.Append ( "; SELECT CAST(scope_identity() AS " );
            sql.Append ( identityType );
            sql.Append ( ")" );
        }
        bFirst = true;
        sql.Append(";");
        values = new StringBuilder ( "VALUES (" );
    } //fin foreach
    return sql.ToString ();
}

0

最初にDBCCを使用して、次に挿入を使用してこの問題を解決しました。たとえば、テーブルが

まず、テーブルの新しい現在のID値をNEW_RESEED_VALUEとして設定します

MyTable {IDCol、colA、colB}

    DBCC CHECKIDENT('MyTable', RESEED, NEW_RESEED_VALUE)

その後、あなたは使うことができます

    insert into MyTable (colA, ColB) select colA, colB from MyTable

これはすべてのレコードを複製しますが、NEW_RESEED_VALUEで始まる新しいIDCol値を使用します。外部キー参照がある場合、それらを削除または移動すると、より高いID値の重複行を削除できます。


1
これはまともなアイデアですが、New_reseed_valueは現在のシードであり、使用される次の数値はその値より1大きくなります。あなたは次の挿入行はアイデンティティ10になりたいのであれば、その後、NEW_RESEED_VALUEは9に設定する必要があります
LarryBud

0

次のコードを使用して新しいテーブルを作成できます。

SELECT IDENTITY (int, 1, 1) AS id, column1, column2
INTO dbo.NewTable
FROM dbo.OldTable

次に、古いデータベースを削除し、新しいデータベースの名前を古いデータベースの名前に変更します。:column1とcolumn2は、新しいテーブルに保持したい古いテーブルのすべての列を表します。


0

主キーの値を別の数値に変更する必要がある場合(例:123-> 1123)。identityプロパティは、PK値の変更をブロックします。Set Identity_insertは機能しません。カスケード削除を行っている場合(参照整合性チェックをオフにしない限り)、挿入/削除を行うことはお勧めできません。

このスクリプトは、PKのIDをオフにします。

***********************

sp_configure 'allow update', 1
go
reconfigure with override
go


update syscolumns set colstat = 0 --turn off bit 1 which indicates identity column
where id = object_id('table_name') and name = 'column_name'
go


exec sp_configure 'allow update', 0
go
reconfigure with override
go

***********************

次に、外部キー参照を更新するように関係を設定できます。または、関係の強制をオフにする必要があります。このSOリンクは、T-SQLを使用して外部キー制約を一時的に無効にする方法を示してい ます。

これで、更新を行うことができます。同じ列名に基づいてすべての更新SQLを書き込む短いスクリプトを作成しました(私の場合、CaseIDを1,000,000増やす必要がありました:

select 
'update ['+c.table_name+'] SET ['+Column_Name+']=['+Column_Name+']+1000000'
from Information_Schema.Columns as c
JOIN Information_Schema.Tables as t ON t.table_Name=c.table_name and t.Table_Schema=c.table_schema and t.table_type='BASE TABLE'
where Column_Name like 'CaseID' order by Ordinal_position

最後に、参照整合性を再度有効にしてから、主キーのIdentity列を再度有効にします。

注:私はこれらの質問について何人かの人々がなぜ尋ねるのを見ます。私の場合、2番目のインスタンスをシャットダウンできるように、2番目の本番インスタンスのデータをマスターDBにマージする必要があります。操作データのすべてのPK / FKが衝突しないようにする必要があります。メタデータFKは同じです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.