İLK
Muhtemelen her üç sütun gerekmez: old_id, external_id, new_id. Bir olan new_idsütun, IDENTITYeklediğinizde bile her satır için yeni bir değere sahip olacaktır external_id. Ancak, old_idve arasında external_id, bunlar birbirini tamamen dışlar: ya zaten bir old_iddeğer var ya da mevcut kavramada, bu sütun sadece veya NULLkullanıldığında olacak . Halihazırda var olan (yani değeri olan bir satır) yeni bir "harici" kimlik eklemeyeceğiniz ve herhangi bir yeni değer gelmeyeceği için , kullanılan bir sütun olabilir her iki amaç için.external_idnew_idold_idold_id
Bu nedenle, external_idsütundan kurtulun ve old_idbenzer bir şey olarak yeniden adlandırın old_or_external_id. Bu, hiçbir şeyde gerçek bir değişiklik gerektirmemeli, ancak bazı komplikasyonları azaltmalıdır. Eklemek için external_iduygulama kodu zaten yazıldıysa, en fazla "eski" değerler içeriyor olsa bile sütunu aramanız gerekebilir external_id.
Bu, yeni yapıyı sadece:
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
Artık 12 bayt yerine satır başına yalnızca 8 bayt eklediniz ( SPARSEseçeneği veya Veri Sıkıştırma'yı kullanmadığınız varsayılarak ). Ve herhangi bir kodu, T-SQL veya Uygulama kodunu değiştirmeniz gerekmez.
İKİNCİ
Bu sadeleştirme yolunda devam ederek, geriye ne bıraktığımıza bakalım:
old_or_external_idKolon ya da zaten değerlere sahiptir, ya da uygulama yeni bir değer verilecek veya bırakılacaktır NULL.
- Her
new_idzaman yeni bir değer oluşturulur, ancak bu değer yalnızca old_or_external_idsütun ise kullanılır NULL.
Hem old_or_external_idve hem de değerlere ihtiyaç duyacağınız bir zaman asla olmaz new_id. Her iki sütun nedeniyle değerlere sahip olduğunda Evet, bazı zamanlar olacaktır new_idbir varlık IDENTITY, ancak bu new_iddeğerler dikkate alınmaz. Yine, bu iki alan birbirini dışlar. Peki şimdi ne olacak?
Şimdi neden external_idilk başta ihtiyacımız olduğuna bakabiliriz . IDENTITYKullanarak bir sütuna eklenmenin mümkün olduğunu göz önünde bulundurarak, SET IDENTITY_INSERT {table_name} ON;hiçbir şema değişikliği yapmadan kurtulabilir ve uygulama kodunuzu yalnızca INSERTifadeleri / işlemleri SET IDENTITY_INSERT {table_name} ON;ve SET IDENTITY_INSERT {table_name} OFF;ifadeleri sarmak için değiştirebilirsiniz . Daha sonra, IDENTITYsütunu (yeni oluşturulan değerler için) sıfırlamak için hangi başlangıç aralığını belirlemeniz gerekir, çünkü daha yüksek bir değer eklemek sonraki otomatik oluşturulan değerin geçerli MAX değerinden büyük olmalıdır. Ancak her zaman IDENT_CURRENT değerinin altında bir değer ekleyebilirsiniz .
old_or_external_idVe new_idsütunlarını birleştirmek, otomatik olarak oluşturulan değerler ile uygulama tarafından oluşturulan değerler arasında üst üste binen bir değer durumuna geçme şansını da artırmaz, çünkü 2 veya hatta 3 sütuna sahip olma amacı, bunları Birincil Anahtar değerinde birleştirmektir. ve bunlar her zaman benzersiz değerlerdir.
Bu yaklaşımda, yapmanız gerekenler:
Tabloları şu şekilde bırakın:
PkId INT IDENTITY(1,1) PRIMARY KEY
Bu, her satıra 8 veya 12 yerine 0 bayt ekler.
- Uygulama tarafından oluşturulan değerler için başlangıç aralığını belirleyin. Bunlar, her bir tablodaki geçerli MAX değerinden daha büyük olacak, ancak otomatik olarak oluşturulan değerler için minimum değerden daha düşük olacaktır.
- Otomatik olarak oluşturulan aralığın hangi değerden başlaması gerektiğini belirleyin. Geçerli MAX değer arasındaki sürü oda var olmalıdır ve üst sınırda bilerek büyümeye oda bol biraz üzerinde 2140000000 olduğunu. Daha sonra bu yeni minimum tohum değerini DBCC CHECKIDENT aracılığıyla ayarlayabilirsiniz .
- Uygulama kodu INSERT'leri
SET IDENTITY_INSERT {table_name} ON;ve SET IDENTITY_INSERT {table_name} OFF;ifadeleri sarın .
İKİNCİ, Bölüm B
Doğrudan yukarıda belirtilen yaklaşımın bir varyasyonu, App kodu değerlerin -1 ile başlayıp oradan aşağıya inmesi olacaktır . Bu IDENTITYdeğerleri yükselen değerler olarak bırakır . Buradaki fayda, yalnızca şemayı karmaşıklaştırmakla kalmaz, aynı zamanda çakışan kimliklere girme konusunda da endişelenmenize gerek yoktur (uygulama tarafından oluşturulan değerler yeni otomatik oluşturulan aralığa girerse). Bu, yalnızca zaten negatif kimlik değerleri kullanmıyorsanız bir seçenektir (ve insanların otomatik olarak oluşturulan sütunlarda negatif değerler kullanması oldukça nadir görünüyor, bu nedenle çoğu durumda olası bir olasılık olmalıdır).
Bu yaklaşımda, yapmanız gerekenler:
Tabloları şu şekilde bırakın:
PkId INT IDENTITY(1,1) PRIMARY KEY
Bu, her satıra 8 veya 12 yerine 0 bayt ekler.
- Uygulama tarafından oluşturulan değerler için başlangıç aralığı olacaktır
-1.
- Uygulama kodu INSERT'leri
SET IDENTITY_INSERT {table_name} ON;ve SET IDENTITY_INSERT {table_name} OFF;ifadeleri sarın .
Burada yine de yapmanız gerekir IDENTITY_INSERT, ancak: yeni sütun eklemezsiniz, hiçbir IDENTITYsütunu "yeniden düzenlemenize" gerek yoktur ve gelecekteki çakışma riski yoktur.
İKİNCİ, Bölüm 3
Bu yaklaşımın son bir varyasyonu muhtemelen IDENTITYsütunları değiştirmek ve bunun yerine Dizileri kullanmak olacaktır . Bu yaklaşımı benimsemenin nedeni, uygulama kodu değerlerini şu şekilde girebilmektir: pozitif, otomatik oluşturulan aralığın üstünde (aşağıda değil) ve gerek yoktur SET IDENTITY_INSERT ON / OFF.
Bu yaklaşımda, yapmanız gerekenler:
- CREATE SEQUENCE kullanarak Dizi Oluşturma
IDENTITYSütunu, IDENTITYözelliği olmayan ancak NEXT VALUE FOR işlevini DEFAULTkullanarak bir Kısıtlama içeren yeni bir sütuna kopyalayın :
PkId INT PRIMARY KEY CONSTRAINT [DF_TableName_NextID] DEFAULT (NEXT VALUE FOR...)
Bu, her satıra 8 veya 12 yerine 0 bayt ekler.
- Uygulama tarafından oluşturulan değerlerin başlangıç aralığı, otomatik olarak oluşturulan değerlerin yaklaşacağını düşündüğünüz değerin çok üzerinde olacaktır.
- Uygulama kodu INSERT'leri
SET IDENTITY_INSERT {table_name} ON;ve SET IDENTITY_INSERT {table_name} OFF;ifadeleri sarın .
Ancak , ya kodlardan biri ile ya SCOPE_IDENTITY()da @@IDENTITYhala düzgün bir şekilde çalışması gerektiği için, Sekanslara geçiş şu anda bir seçenek değildir, çünkü Sekanslar için bu fonksiyonların eşdeğeri olmadığı anlaşılmaktadır :-(. Sad!