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 IDENTITY
kolom, dan (2) memastikan bahwa IDENTITY
permulaan 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 IDENTITY
kolom yang akan dimulai pada 21 untuk catatan berikutnya yang dimasukkan. Untuk contoh ini, kolom xyz
mewakili 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_temp
dan atur kolom itu ke nilai id
kolom yang ada :
ALTER TABLE dbo.ident_test ADD id_temp int NULL;
UPDATE dbo.ident_test SET id_temp=id;
Selanjutnya, kita perlu menjatuhkan id
kolom yang ada (Anda tidak bisa hanya "menambahkan" IDENTITY
ke 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_INSERT
pada tabel, yang berarti bahwa Anda dapat secara manual menentukan nilai-nilai IDENTITY
kolom ketika Anda memasukkan baris baru (meskipun tidak memperbarui baris yang ada).
SET IDENTITY_INSERT dbo.ident_test ON;
Dengan set itu, DELETE
semua baris dalam tabel, tetapi baris yang Anda hapus berada OUTPUT
di tabel yang sama - tetapi dengan nilai spesifik untuk id
kolom (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 IDENTITY
kolom, sehingga catatan berikutnya id
akan 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 .. INTO
tidak 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 id
kolom 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 INSERT
dan DELETE
memicu 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
?