Bagaimana cara memperbarui Kolom Identitas di SQL Server?


196

Saya memiliki database SQL Server dan saya ingin mengubah kolom identitas karena dimulai dengan angka besar 10010dan ini terkait dengan tabel lain, sekarang saya memiliki 200 catatan dan saya ingin memperbaiki masalah ini sebelum catatan meningkat.

Apa cara terbaik untuk mengubah atau mengatur ulang kolom ini?

Jawaban:


270

Anda tidak dapat memperbarui kolom identitas.

SQL Server tidak memungkinkan untuk memperbarui kolom identitas tidak seperti apa yang dapat Anda lakukan dengan kolom lain dengan pernyataan pembaruan.

Meskipun ada beberapa alternatif untuk mencapai persyaratan serupa.

  • Ketika nilai kolom Identitas perlu diperbarui untuk catatan baru

Gunakan DBCC CHECKIDENT yang memeriksa nilai identitas saat ini untuk tabel dan jika diperlukan, ubah nilai identitas.

DBCC CHECKIDENT('tableName', RESEED, NEW_RESEED_VALUE)
  • Ketika nilai kolom Identitas perlu diperbarui untuk catatan yang ada

Gunakan IDENTITY_INSERT yang memungkinkan nilai eksplisit untuk dimasukkan ke kolom identitas tabel.

SET IDENTITY_INSERT YourTable {ON|OFF}

Contoh:

-- 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 Atur ulang catatan baru berikutnya, tetapi apa yang saya inginkan sekarang untuk mengubah catatan yang ada.
Abdulsalam Elsharif

bisakah Anda memberi contoh?
Abdulsalam Elsharif

38
@sachin ini bukan memperbarui IDENTITAS yang ada, ini memasukkan secara manual
Phill Greggan

3
@PhillGreggan ya, ini adalah solusi terbaik untuk mencapai ini. Anda tidak dapat memperbarui kolom Identitas saat Anda memperbarui yang normal.
Sachin

17
Jawaban yang diterima ini tidak menjawab pertanyaan, yaitu bagaimana cara memperbarui kolom identitas (mis UPDATE YourTable SET IdentityCol = 13.). SET IDENTITY_INSERT YourTable ONhanya memperbolehkan INSERT, bukan UPDATE.
Ian Boyd

62

Jika pertanyaan Anda benar, Anda ingin melakukan sesuatu seperti

update table
set identity_column_name = some value

Biarkan saya memberi tahu Anda, ini bukan proses yang mudah dan tidak disarankan untuk menggunakannya, karena mungkin ada beberapa yang foreign keyterkait dengannya.

Tapi di sini ada beberapa langkah untuk melakukannya. Silakan ambil satu back-upmeja

Langkah 1- Pilih tampilan desain tabel

masukkan deskripsi gambar di sini

Langkah 2- Matikan kolom identitas

masukkan deskripsi gambar di sini

Sekarang Anda dapat menggunakan updatekueri.

Sekarang redolangkah 1 dan langkah 2 dan Nyalakan kolom identitas

Referensi


1
Saya punya meja lain yang terkait dengan tabel ini, saya tidak bisa melakukan itu
Abdulsalam Elsharif

4
Oleh karena itu pernyataan itu tidak disarankan :)
Luv

3
@AbdusalamElsherif Tapi Anda bertanya bagaimana cara mengubah kolom identitas.
paparazzo

@luv setidaknya Anda telah menjawab pertanyaan yang diajukan
Phill Greggan

Saya menggunakan prosedur ini untuk mengatur id di database pengembangan saya. Akan lebih baik jika ada perintah yang membiarkan saya melakukannya, tetapi ini berhasil.
Jeff Davis

56

Kamu butuh

set identity_insert YourTable ON

Kemudian hapus baris Anda dan masukkan kembali dengan identitas yang berbeda.

Setelah Anda selesai memasukkan, jangan lupa mematikan identitas_insert

set identity_insert YourTable OFF

Ini jauh lebih mudah dan lebih aman daripada mematikan Identity untuk kolom!
Pelindung satu

Ini lebih aman, dan mudah untuk sejumlah kecil catatan, tetapi tidak menjawab pertanyaan dengan benar. Mematikan identitas, meskipun lebih berbahaya dan terkadang tidak mungkin, memungkinkan Anda untuk memperbarui kolom identitas.
Matius Hudson,

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
Hanya tip kinerja jika tabel sangat besar, alih-alih melakukan penghapusan pada tabel, lakukan Tabel Truncate yourTable. Ini instan. Perhatian, jangan kembali dengan terpotong karena tidak dicatat.
kuklei


5

salin meja Anda ke tabel baru tanpa kolom identitas.

    select columns into newtable from yourtable

tambahkan kolom identitas ke tabel baru dengan seed baru dan menjadikannya sebagai kunci utama

    ALTER TABLE tableName ADD id MEDIUMINT NOT NULL AUTO_INCREMENT KEY

3
DBCC CHECKIDENT(table_name, RESEED, value)

table_name = berikan tabel yang ingin Anda setel ulang nilainya

value = nilai awal menjadi nol, untuk memulai kolom identitas dengan 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

Saat menggunakan Identity_Insert jangan lupa untuk memasukkan nama kolom karena sql tidak akan memungkinkan Anda untuk menyisipkan tanpa menentukannya


2

Anda juga dapat menggunakan SET IDENTITY INSERTuntuk memungkinkan Anda memasukkan nilai ke dalam kolom identitas.

Contoh:

SET IDENTITY_INSERT dbo.Tool ON
GO

Dan kemudian Anda dapat memasukkan ke dalam kolom identitas nilai-nilai yang Anda butuhkan.


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

Namun kode di atas hanya berfungsi jika tidak ada hubungan kunci primer-asing


1

Solusi lengkap untuk programmer C # menggunakan command builder

Pertama-tama, Anda harus mengetahui fakta ini:

  • Bagaimanapun, Anda tidak dapat memodifikasi kolom identitas, jadi Anda harus menghapus baris dan menambahkan kembali dengan identitas baru.
  • Anda tidak dapat menghapus properti identitas dari kolom (Anda harus menghapus ke kolom)
  • Pembuat perintah khusus dari .net selalu melewatkan kolom identitas, jadi Anda tidak dapat menggunakannya untuk tujuan ini.

Jadi, sekali tahu itu, apa yang harus Anda lakukan adalah. Baik program pernyataan Sisipan SQL Anda sendiri, atau program yang Anda miliki pembuat perintah insert. Atau gunakan yang ini yang saya programkan untuk Anda. Diberikan DataTable, menghasilkan skrip SQL Insert:

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

Saya telah memecahkan masalah ini terlebih dahulu menggunakan DBCC dan kemudian menggunakan insert. Misalnya jika meja Anda

Pertama-tama atur Nilai ID baru saat ini di atas tabel sebagai NEW_RESEED_VALUE

MyTable {IDCol, colA, colB}

    DBCC CHECKIDENT('MyTable', RESEED, NEW_RESEED_VALUE)

maka Anda bisa menggunakannya

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

Ini akan menggandakan semua catatan Anda tetapi menggunakan nilai IDCol baru yang dimulai dengan NEW_RESEED_VALUE. Anda kemudian dapat menghapus baris duplikat Nilai ID yang lebih tinggi setelah Anda menghapus / memindahkan referensi kunci asing mereka, jika ada.


1
Ini adalah ide yang layak, tetapi nilai New_reseed_v adalah unggulan saat ini, dan angka berikutnya yang akan digunakan adalah 1 lebih dari nilai itu. Jadi, jika Anda ingin baris yang disisipkan berikutnya menjadi identitas 10, maka NEW_RESEED_VALUE harus disetel ke 9.
LarryBud

0

Anda bisa membuat tabel baru menggunakan kode berikut.

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

Kemudian hapus db lama, dan ganti nama db baru dengan nama db lama. Catatan : bahwa kolom1 dan kolom2 mewakili semua kolom di tabel lama Anda yang ingin Anda simpan di tabel baru Anda.


0

Jika Anda secara khusus perlu mengubah nilai kunci utama ke nomor yang berbeda (mis. 123 -> 1123). Properti identitas memblokir mengubah nilai PK. Setel Identity_insert tidak akan berfungsi. Melakukan Sisipan / Hapus tidak disarankan jika Anda memiliki penghapusan cascading (kecuali jika Anda mematikan pemeriksaan integritas referensial).

Script ini akan mematikan identitas pada PK:

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

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

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

Selanjutnya, Anda dapat mengatur hubungan sehingga mereka akan memperbarui referensi kunci asing. Atau Anda harus mematikan penegakan hubungan. Tautan SO ini menunjukkan caranya: Bagaimana batasan kunci asing sementara dapat dinonaktifkan menggunakan T-SQL?

Sekarang, Anda dapat melakukan pembaruan. Saya menulis sebuah skrip pendek untuk menulis semua pembaruan SQL saya berdasarkan nama kolom yang sama (dalam kasus saya, saya perlu meningkatkan CaseID dengan 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

Terakhir, aktifkan kembali integritas referensial dan aktifkan kembali kolom Identity pada kunci utama.

Catatan: Saya melihat beberapa orang menanyakan pertanyaan ini MENGAPA. Dalam kasus saya, saya harus menggabungkan data dari instance produksi kedua menjadi master DB sehingga saya bisa mematikan instance kedua. Saya hanya perlu semua data operasi PK / FK untuk tidak bertabrakan. Meta-data FK identik.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.