Saya membuat tabel dalam DB yang sudah ada di DB lain. Awalnya diisi dengan data DB lama. PK tabel harus menerima nilai-nilai yang sudah ada pada catatan itu, jadi itu tidak bisa autoincrement.
Sekarang saya perlu tabel baru untuk memiliki PK sebagai autoincrement. Tetapi bagaimana saya bisa melakukan itu setelah PK sudah ada dan memiliki data?
IDENTITY
?Jawaban:
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 bahwaIDENTITY
permulaan dari nilai terbaru di baris yang ada.Pertama, beberapa data uji untuk dimainkan:
Tujuannya adalah untuk membuat kolom kunci utama tabel
id
,, sebuahIDENTITY
kolom yang akan dimulai pada 21 untuk catatan berikutnya yang dimasukkan. Untuk contoh ini, kolomxyz
mewakili semua kolom tabel lainnya.Sebelum Anda melakukan apa pun, harap baca peringatan di bagian bawah pos ini.
Pertama, jika terjadi kesalahan:
Sekarang, mari kita tambahkan kolom kerja sementara,
id_temp
dan atur kolom itu ke nilaiid
kolom yang ada :Selanjutnya, kita perlu menjatuhkan
id
kolom yang ada (Anda tidak bisa hanya "menambahkan"IDENTITY
ke kolom yang ada, Anda harus membuat kolom sebagaiIDENTITY
). Kunci utama juga harus pergi, karena kolom tergantung padanya.... dan tambahkan kolom lagi, kali ini sebagai
IDENTITY
, bersama dengan kunci utama:Di sinilah mulai menarik. Anda dapat mengaktifkan
IDENTITY_INSERT
pada tabel, yang berarti bahwa Anda dapat secara manual menentukan nilai-nilaiIDENTITY
kolom ketika Anda memasukkan baris baru (meskipun tidak memperbarui baris yang ada).Dengan set itu,
DELETE
semua baris dalam tabel, tetapi baris yang Anda hapus beradaOUTPUT
di tabel yang sama - tetapi dengan nilai spesifik untukid
kolom (dari kolom cadangan).Setelah selesai, balikkan
IDENTITY_INSERT
kembali.Jatuhkan kolom sementara yang kami tambahkan:
Dan akhirnya, masukkan kembali
IDENTITY
kolom, sehingga catatan berikutnyaid
akan dilanjutkan setelah angka tertinggi yang ada diid
kolom:Memeriksa tabel contoh, yang tertinggi
id
adalah 20.Tambahkan baris lain dan periksa yang baru
IDENTITY
:Pada contoh, baris baru akan ditampilkan
id=21
. Akhirnya, jika Anda senang, lakukan transaksi: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
danDELETE
memicu di atas meja.Jika membuat ulang tabel adalah suatu opsi:
Jika membuat ulang tabel adalah opsi untuk Anda, semuanya jauh lebih sederhana:
id
kolom sebagaiIDENTITY
,IDENTITY_INSERT ON
untuk meja,IDENTITY_INSERT OFF
, dansumber
IDENTITY_INSERT ON
, mengisi dan menonaktifkannya. Itu yang ingin saya lakukan, tetapi tidak tahu MSSQL mendukungnya.Menggunakan UPDATE, DELETE atau INSERT untuk memindahkan data dapat menghabiskan banyak waktu dan menggunakan sumber daya (IO) pada data dan file log / disk. Dimungkinkan untuk menghindari mengisi log transaksi dengan berpotensi banyak catatan saat mengerjakan tabel besar: Menggunakan pergantian partisi, hanya metadata yang diubah.
Tidak ada pergerakan data yang terlibat dan karena itu dilakukan dengan sangat cepat (hampir seketika).
Tabel sampel
Pertanyaannya tidak menunjukkan tabel asli DDL. DDL berikut akan digunakan sebagai contoh dalam jawaban ini:
Setengah lusin id acak dummy dari 0 hingga 15 ditambahkan dengan kueri ini:
Contoh data dalam
IdT
Meja baru dengan
IDENTITY(0, 1)
Satu-satunya masalah
idT
adalah kurangnyaIDENTITY(0, 1)
properti pada id. Tabel baru dengan struktur yang sama danIDENTITY(0, 1)
dibuat:Selain itu
IDENTITY(0, 1)
,idT_Switch
identik denganidT
.Kunci Asing
Kunci asing pada
idT
harus dihapus untuk memungkinkan teknik ini digunakan.Sakelar Partisi
The
idT
danidT_Switch
tabel memiliki struktur yang kompatibel. Alih-alih menggunakanDELETE
,UPDATE
danINSERT
pernyataan untuk memindahkan baris dariidT
keidT_Switch
atau padaidT
dirinya sendiri,ALTER TABLE ... SWITCH
dapat digunakan:'Partisi' tunggal
PK_idT
(seluruh tabel) dipindahkan kePK_idT_Switch
(dan sebaliknya).idT
sekarang berisi 0 baris danidT_Switch
mengandung 6 baris.Anda dapat menemukan daftar lengkap persyaratan kompatibilitas sumber dan tujuan di sini:
Mentransfer Data secara Efisien dengan Menggunakan Partition Switching
Perhatikan penggunaan
SWITCH
ini tidak memerlukan Edisi Perusahaan, karena tidak ada partisi yang eksplisit. Tabel unpartitioned dianggap sebagai tabel dengan satu partisi dari SQL Server 2005 dan seterusnya.Menggantikan
idT
idT
sekarang kosong dan tidak berguna dan dapat dijatuhkan:idT_Switch
dapat diubah namanya dan akan menggantikanidT
tabel lama :Kunci asing
Kunci asing dapat ditambahkan lagi ke
idT
tabel baru . Apa pun yang sebelumnya dihapus dariidT
untuk membuat tabel yang kompatibel untuk beralih juga perlu diulang.Dipasang kembali
Perintah ini mengembalikan 0. Tabel idT berisi 6 baris dengan MAX (id) = 15. DBCC CHECKIDENT (table_name) dapat digunakan:
Karena 15 lebih besar dari 0, maka akan secara otomatis ditampilkan kembali tanpa mencari MAX (id):
IDENT_CURRENT sekarang mengembalikan 15 .
Uji dan tambahkan data
INSERT
Pernyataan sederhana :Menambahkan baris ini:
The
id
kolom sekarang menggunakan identitas dan nilai yang baru dimasukkan memang 16 (15 + 1).Informasi lebih lanjut
Ada pertanyaan dan jawaban terkait dengan latar belakang lebih lanjut tentang
SWITCH
teknik di sini:Mengapa menghapus properti Identity pada kolom tidak didukung
sumber
Jika Anda ingin memulai dengan nilai identitas baru, Anda perlu memasukkan kembali identitas Anda. Lihat dokumentasi untuk
CHECKIDENT
sumber
Aktifkan dan Nonaktifkan IDENTITY_INSERT
Jika meja Anda TABLE_A, maka
sumber