SQL Server sistem tarafından oluşturulan kısıtlama adlarında çakışmalar oluşturabilir mi?
Bu, kısıtlama türüne ve SQL Server sürümüne bağlıdır.
CREATE TABLE T1
(
A INT PRIMARY KEY CHECK (A > 0),
B INT DEFAULT -1 REFERENCES T1,
C INT UNIQUE,
CHECK (C > A)
)
SELECT name,
object_id,
CAST(object_id AS binary(4)) as object_id_hex,
CAST(CASE WHEN object_id >= 16000057 THEN object_id -16000057 ELSE object_id +2131483591 END AS BINARY(4)) AS object_id_offset_hex
FROM sys.objects
WHERE parent_object_id = OBJECT_ID('T1')
ORDER BY name;
drop table T1
Örnek Sonuçlar 2008
+--------------------------+-----------+---------------+----------------------+
| name | object_id | object_id_hex | object_id_offset_hex |
+--------------------------+-----------+---------------+----------------------+
| CK__T1__1D498357 | 491357015 | 0x1D498357 | 0x1C555F1E |
| CK__T1__A__1A6D16AC | 443356844 | 0x1A6D16AC | 0x1978F273 |
| DF__T1__B__1B613AE5 | 459356901 | 0x1B613AE5 | 0x1A6D16AC |
| FK__T1__B__1C555F1E | 475356958 | 0x1C555F1E | 0x1B613AE5 |
| PK__T1__3BD019AE15A8618F | 379356616 | 0x169C85C8 | 0x15A8618F |
| UQ__T1__3BD019A91884CE3A | 427356787 | 0x1978F273 | 0x1884CE3A |
+--------------------------+-----------+---------------+----------------------+
Örnek Sonuçlar 2017
+--------------------------+------------+---------------+----------------------+
| name | object_id | object_id_hex | object_id_offset_hex |
+--------------------------+------------+---------------+----------------------+
| CK__T1__59FA5E80 | 1509580416 | 0x59FA5E80 | 0x59063A47 |
| CK__T1__A__571DF1D5 | 1461580245 | 0x571DF1D5 | 0x5629CD9C |
| DF__T1__B__5812160E | 1477580302 | 0x5812160E | 0x571DF1D5 |
| FK__T1__B__59063A47 | 1493580359 | 0x59063A47 | 0x5812160E |
| PK__T1__3BD019AE0A4A6932 | 1429580131 | 0x5535A963 | 0x5441852A |
| UQ__T1__3BD019A981F522E0 | 1445580188 | 0x5629CD9C | 0x5535A963 |
+--------------------------+------------+---------------+----------------------+
Varsayılan kısıtlamalar için, kontrol kısıtlamaları ve yabancı anahtar kısıtlamaları, otomatik oluşturulan adın son 4 baytı, sınırlamanın nesne kimliğinin onaltılık sürümüdür. objectid
Benzersiz garantili olduğu gibi ad da benzersiz olmalıdır. Sybase'de de bu kullanımtabname_colname_objectid
Sybase'in kullandığı benzersiz kısıtlamalar ve birincil anahtar kısıtlamaları için
tabname_colname_tabindid; burada tabindid, tablo kimliğinin ve dizin kimliğinin dize birleşimidir
Bu da benzersizliği garanti eder.
SQL Server bu düzeni kullanmaz.
Hem SQL Server 2008 hem de 2017'de sistem tarafından üretilen adın sonunda 8 baytlık bir dize kullanır, ancak algoritma, son 4 baytın nasıl üretildiğine göre değişmiştir.
2008 yılında son 4 bayt kaymış bir imzalı tamsayı sayacı temsil object_id
tarafından -16000057
azami imzalı int etrafında herhangi bir olumsuz değer sarma ile. (Bunun önemi 16000057
, bunun art arda oluşturulanlar arasında uygulanan artış olmasıdırobject_id
). Bu hala benzersizliği garanti eder.
2012 yılında, kısıtlamanın object_id değeri ile ismin son 8 karakterini imzalı bir int'in onaltılı gösterimi olarak ele alarak elde edilen tamsayı arasında hiçbir desen görmüyorum.
2017'deki çağrı yığınındaki işlev adları, artık ad oluşturma işleminin bir parçası olarak bir GUID oluşturduğunu göstermektedir (2008'de hiç bahsetmiyorum MDConstraintNameGenerator
). Sanırım bu bir rastgelelik kaynağı sağlamak. Açıkçası, bu 4 baytta GUID'den 16 baytın tamamını kullanmıyor ancak kısıtlamalar arasında değişiyor.
Yeni algoritmanın, sizinki gibi aşırı durumlarda bazı artan çarpışma olasılığı pahasına bir miktar verimlilik nedeni ile yapıldığını düşünüyorum.
PK'nın tablo adı önekini ve sütun adını (bu son 8'den önceki 8 karakteri etkilediği sürece) olası hale gelmeden önce on binlerce tablo için aynı olmasını gerektirdiğinden, ancak oldukça çoğaltılabildiğinden, bu oldukça patolojik bir durumdur. aşağıdaki ile kolayca.
CREATE OR ALTER PROC #P
AS
SET NOCOUNT ON;
DECLARE @I INT = 0;
WHILE 1 = 1
BEGIN
EXEC ('CREATE TABLE abcdefghijklmnopqrstuvwxyz' + @I + '(C INT PRIMARY KEY)');
SET @I +=1;
END
GO
EXEC #P
SQL Server 2017'de yeni oluşturulan bir veritabanında çalıştırılan örnek bir dakika içinde başarısız oldu (50.931 tablo oluşturulduktan sonra)
Msg 2714, Seviye 16, Durum 30, Satır 15 Veritabanında zaten 'PK__abcdefgh__3BD019A8175067CE' adlı bir nesne var. Msg 1750, Seviye 16, Durum 1, Satır 15 Kısıtlama veya dizin oluşturulamadı. Önceki hatalara bakın.