PERTAMA
Anda mungkin tidak perlu semua tiga kolom: old_id
, external_id
, new_id
. The new_id
kolom, menjadi IDENTITY
, akan memiliki nilai baru yang dihasilkan untuk setiap baris, bahkan ketika Anda masukkan ke dalam external_id
. Tetapi, antara old_id
dan external_id
, itu cukup banyak saling eksklusif: apakah sudah ada old_id
nilai atau kolom itu, dalam konsepsi saat ini, hanya akan NULL
jika menggunakan external_id
atau new_id
. Karena Anda tidak akan menambahkan id "eksternal" baru ke baris yang sudah ada (yaitu yang memiliki old_id
nilai), dan tidak akan ada nilai baru yang masuk old_id
, maka mungkin ada satu kolom yang digunakan untuk kedua tujuan.
Jadi, singkirkan external_id
kolom dan ganti nama old_id
menjadi sesuatu seperti old_or_external_id
atau apa pun. Ini seharusnya tidak memerlukan perubahan nyata untuk apa pun, namun mengurangi beberapa komplikasi. Paling-paling Anda mungkin perlu memanggil kolom external_id
, bahkan jika itu berisi nilai-nilai "lama", jika kode aplikasi sudah ditulis untuk dimasukkan external_id
.
Itu mengurangi struktur baru menjadi adil:
PkId AS AS COALESCE(old_or_external_id, new_id, -1) PERSISTED NOT NULL,
old_or_external_id INT NULL, -- values from existing record OR passed in from app
new_id INT IDENTITY(2000000, 1) NOT NULL
Sekarang Anda hanya menambahkan 8 byte per baris, bukan 12 byte (dengan asumsi Anda tidak menggunakan SPARSE
opsi atau Kompresi Data). Dan Anda tidak perlu mengubah kode apa pun, T-SQL atau kode Aplikasi.
KEDUA
Melanjutkan jalan penyederhanaan ini, mari kita lihat apa yang tersisa:
- The
old_or_external_id
Kolom baik memiliki nilai-nilai yang sudah, atau akan diberikan nilai baru dari aplikasi, atau akan ditinggalkan sebagai NULL
.
- The
new_id
akan selalu memiliki nilai baru yang dihasilkan, tetapi nilai yang hanya akan digunakan jika old_or_external_id
kolom NULL
.
Tidak pernah ada saat ketika Anda membutuhkan nilai di keduanya old_or_external_id
dan new_id
. Ya, akan ada saat-saat ketika kedua kolom memiliki nilai karena new_id
menjadi IDENTITY
, tetapi new_id
nilai - nilai itu diabaikan. Sekali lagi, kedua bidang ini saling eksklusif. Jadi bagaimana sekarang?
Sekarang kita bisa melihat mengapa kita membutuhkannya external_id
. Menimbang bahwa dimungkinkan untuk memasukkan ke dalam IDENTITY
kolom menggunakan SET IDENTITY_INSERT {table_name} ON;
, Anda bisa lolos tanpa membuat perubahan skema sama sekali, dan hanya memodifikasi kode aplikasi Anda untuk membungkus INSERT
pernyataan / operasi SET IDENTITY_INSERT {table_name} ON;
dan SET IDENTITY_INSERT {table_name} OFF;
pernyataan. Anda kemudian perlu menentukan rentang awal untuk mereset IDENTITY
kolom ke (untuk nilai yang baru dihasilkan) karena harus jauh di atas nilai-nilai yang akan disisipkan kode Aplikasi karena memasukkan nilai yang lebih tinggi akan menyebabkan nilai yang dihasilkan secara otomatis berikutnya menjadi lebih besar dari nilai MAX saat ini. Tetapi Anda selalu dapat memasukkan nilai yang di bawah nilai IDENT_CURRENT .
Menggabungkan old_or_external_id
dan new_id
kolom juga tidak meningkatkan peluang berlari ke situasi nilai yang tumpang tindih antara nilai yang dibuat secara otomatis dan nilai yang dihasilkan aplikasi karena maksud memiliki kolom 2, atau bahkan 3, adalah untuk menggabungkannya menjadi nilai Kunci Utama, dan itu selalu merupakan nilai unik.
Dalam pendekatan ini, Anda hanya perlu:
Tinggalkan tabel sebagai:
PkId INT IDENTITY(1,1) PRIMARY KEY
Ini menambahkan 0 byte ke setiap baris, bukannya 8, atau bahkan 12.
- Tentukan rentang awal untuk nilai yang dihasilkan aplikasi. Ini akan lebih besar dari nilai MAX saat ini di setiap tabel, tetapi kurang dari apa yang akan menjadi nilai minimum untuk nilai yang dihasilkan secara otomatis.
- Tentukan nilai berapa rentang yang dihasilkan secara otomatis harus dimulai. Seharusnya ada banyak ruang antara nilai MAX saat ini dan banyak ruang untuk tumbuh, mengetahui pada batas atas hanya lebih dari 2,14 miliar. Anda kemudian dapat menetapkan nilai seed minimum baru ini melalui DBCC CHECKIDENT .
- Bungkus kode aplikasi Sisipkan
SET IDENTITY_INSERT {table_name} ON;
dan SET IDENTITY_INSERT {table_name} OFF;
pernyataan.
KEDUA, Bagian B
Variasi pada pendekatan yang dicatat secara langsung di atas adalah memiliki nilai-nilai penyisipan kode aplikasi yang dimulai dengan -1 dan turun dari sana. Ini meninggalkan IDENTITY
nilai - nilai sebagai satu-satunya yang naik . Manfaatnya di sini adalah Anda tidak hanya tidak memperumit skema, Anda juga tidak perlu khawatir akan mengalami ID yang tumpang tindih (jika nilai yang dihasilkan aplikasi masuk ke rentang baru yang dibuat secara otomatis). Ini hanya opsi jika Anda belum menggunakan nilai ID negatif (dan tampaknya sangat jarang bagi orang untuk menggunakan nilai negatif pada kolom yang dibuat secara otomatis sehingga ini kemungkinan kemungkinan dalam sebagian besar situasi).
Dalam pendekatan ini, Anda hanya perlu:
Tinggalkan tabel sebagai:
PkId INT IDENTITY(1,1) PRIMARY KEY
Ini menambahkan 0 byte ke setiap baris, bukannya 8, atau bahkan 12.
- Rentang awal untuk nilai yang dihasilkan aplikasi akan menjadi
-1
.
- Bungkus kode aplikasi Sisipkan
SET IDENTITY_INSERT {table_name} ON;
dan SET IDENTITY_INSERT {table_name} OFF;
pernyataan.
Di sini Anda masih perlu melakukan IDENTITY_INSERT
, tetapi: Anda tidak menambahkan kolom baru, tidak perlu "memasang kembali" IDENTITY
kolom apa pun , dan tidak memiliki risiko tumpang tindih di masa depan.
KEDUA, Bagian 3
Satu variasi terakhir dari pendekatan ini adalah dengan menukar IDENTITY
kolom dan menggunakan Sekuens . Alasan untuk mengambil pendekatan ini adalah untuk dapat memiliki nilai-nilai penyisipan kode aplikasi yang: positif, di atas rentang yang dibuat secara otomatis (tidak di bawah), dan tidak perlu SET IDENTITY_INSERT ON / OFF
.
Dalam pendekatan ini, Anda hanya perlu:
- Buat Urutan menggunakan CREATE SEQUENCE
Salin IDENTITY
kolom ke kolom baru yang tidak memiliki IDENTITY
properti, tetapi memiliki DEFAULT
kendala menggunakan fungsi VALUE FOR NEXT FOR :
PkId INT PRIMARY KEY CONSTRAINT [DF_TableName_NextID] DEFAULT (NEXT VALUE FOR...)
Ini menambahkan 0 byte ke setiap baris, bukannya 8, atau bahkan 12.
- Rentang awal untuk nilai-nilai yang dihasilkan aplikasi akan jauh di atas apa yang Anda pikir akan mendekati nilai-nilai yang dihasilkan secara otomatis.
- Bungkus kode aplikasi Sisipkan
SET IDENTITY_INSERT {table_name} ON;
dan SET IDENTITY_INSERT {table_name} OFF;
pernyataan.
NAMUN , karena persyaratan bahwa kode dengan salah satu SCOPE_IDENTITY()
atau @@IDENTITY
masih berfungsi dengan benar, beralih ke Sequences saat ini tidak menjadi pilihan karena tampaknya tidak ada yang setara dengan fungsi-fungsi untuk Sequences :-(. Sedih!