Cara saya memahami pertanyaan Anda adalah bahwa Anda memiliki tabel yang sudah ada dengan kolom yang sampai sekarang telah diisi dengan nilai-nilai manual, dan sekarang Anda ingin (1) membuat kolom ini menjadi IDENTITYkolom, dan (2) memastikan bahwa IDENTITYpermulaan dari nilai terbaru di baris yang ada.
Pertama, beberapa data uji untuk dimainkan:
CREATE TABLE dbo.ident_test (
id int NOT NULL,
xyz varchar(10) NOT NULL,
CONSTRAINT PK_ident_test PRIMARY KEY CLUSTERED (id)
);
INSERT INTO dbo.ident_test (id, xyz)
VALUES (1, 'test'),
(2, 'test'),
(5, 'test'),
(6, 'test'),
(10, 'test'),
(18, 'test'),
(19, 'test'),
(20, 'test');
Tujuannya adalah untuk membuat kolom kunci utama tabel id,, sebuah IDENTITYkolom yang akan dimulai pada 21 untuk catatan berikutnya yang dimasukkan. Untuk contoh ini, kolom xyzmewakili semua kolom tabel lainnya.
Sebelum Anda melakukan apa pun, harap baca peringatan di bagian bawah pos ini.
Pertama, jika terjadi kesalahan:
BEGIN TRANSACTION;
Sekarang, mari kita tambahkan kolom kerja sementara, id_tempdan atur kolom itu ke nilai idkolom yang ada :
ALTER TABLE dbo.ident_test ADD id_temp int NULL;
UPDATE dbo.ident_test SET id_temp=id;
Selanjutnya, kita perlu menjatuhkan idkolom yang ada (Anda tidak bisa hanya "menambahkan" IDENTITYke kolom yang ada, Anda harus membuat kolom sebagai IDENTITY). Kunci utama juga harus pergi, karena kolom tergantung padanya.
ALTER TABLE dbo.ident_test DROP CONSTRAINT PK_ident_test;
ALTER TABLE dbo.ident_test DROP COLUMN id;
... dan tambahkan kolom lagi, kali ini sebagai IDENTITY, bersama dengan kunci utama:
ALTER TABLE dbo.ident_test ADD id int IDENTITY(1, 1) NOT NULL;
ALTER TABLE dbo.ident_test ADD CONSTRAINT PK_ident_test PRIMARY KEY CLUSTERED (id);
Di sinilah mulai menarik. Anda dapat mengaktifkan IDENTITY_INSERTpada tabel, yang berarti bahwa Anda dapat secara manual menentukan nilai-nilai IDENTITYkolom ketika Anda memasukkan baris baru (meskipun tidak memperbarui baris yang ada).
SET IDENTITY_INSERT dbo.ident_test ON;
Dengan set itu, DELETEsemua baris dalam tabel, tetapi baris yang Anda hapus berada OUTPUTdi tabel yang sama - tetapi dengan nilai spesifik untuk idkolom (dari kolom cadangan).
DELETE FROM dbo.ident_test
OUTPUT deleted.id_temp AS id, deleted.xyz
INTO dbo.ident_test (id, xyz);
Setelah selesai, balikkan IDENTITY_INSERT kembali.
SET IDENTITY_INSERT dbo.ident_test OFF;
Jatuhkan kolom sementara yang kami tambahkan:
ALTER TABLE dbo.ident_test DROP COLUMN id_temp;
Dan akhirnya, masukkan kembali IDENTITYkolom, sehingga catatan berikutnya idakan dilanjutkan setelah angka tertinggi yang ada diid kolom:
DECLARE @maxid int;
SELECT @maxid=MAX(id) FROM dbo.ident_test;
DBCC CHECKIDENT ("dbo.ident_test", RESEED, @maxid)
Memeriksa tabel contoh, yang tertinggi id adalah 20.
SELECT * FROM dbo.ident_test;
Tambahkan baris lain dan periksa yang baru IDENTITY :
INSERT INTO dbo.ident_test (xyz) VALUES ('New row');
SELECT * FROM dbo.ident_test;
Pada contoh, baris baru akan ditampilkan id=21 . Akhirnya, jika Anda senang, lakukan transaksi:
COMMIT TRANSACTION;
Penting
Ini bukan operasi sepele, dan itu membawa beberapa risiko yang harus Anda ketahui.
Lakukan ini di lingkungan uji khusus. Miliki cadangan. :)
Saya suka menggunakan BEGIN/COMMIT TRANSACTION karena mencegah proses lain dari mengacaukan meja saat Anda sedang mengubahnya, dan itu memberi Anda kemungkinan untuk mengembalikan semuanya jika terjadi kesalahan. Namun, proses lain yang mencoba mengakses tabel Anda sebelum Anda melakukan transaksi Anda akan berakhir menunggu. Ini mungkin sangat buruk jika Anda memiliki meja besar dan / atau Anda berada di lingkungan produksi.
OUTPUT .. INTOtidak akan berfungsi jika tabel target Anda memiliki batasan kunci asing atau salah satu dari sejumlah fitur lain yang saya tidak ingat dari atas kepala saya. Sebagai gantinya Anda bisa memuat data ke dalam tabel sementara, dan kemudian memasukkannya kembali ke tabel asli. Anda mungkin dapat menggunakan peralihan partisi (bahkan jika Anda tidak menggunakan partisi).
Jalankan pernyataan ini satu per satu, bukan sebagai batch atau dalam prosedur tersimpan.
Coba pikirkan hal-hal lain yang mungkin bergantung pada idkolom yang Anda jatuhkan dan ciptakan kembali. Setiap indeks harus dijatuhkan dan dibuat kembali (seperti yang kami lakukan dengan kunci utama). Ingat untuk menuliskan setiap indeks dan batasan yang harus Anda buat ulang sebelumnya.
Nonaktifkan apa pun INSERTdan DELETEmemicu di atas meja.
Jika membuat ulang tabel adalah suatu opsi:
Jika membuat ulang tabel adalah opsi untuk Anda, semuanya jauh lebih sederhana:
- Buat tabel kosong, dengan
id kolom sebagaiIDENTITY ,
- Set
IDENTITY_INSERT ON untuk meja,
- Isi tabel,
- Set
IDENTITY_INSERT OFF , dan
- Mempelajari kembali identitas.
IDENTITY?