Bisakah SQL Server membuat tabrakan dalam nama kendala yang dihasilkan sistem?
Ini tergantung pada jenis batasan dan versi SQL Server.
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
Contoh Hasil 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 |
+--------------------------+-----------+---------------+----------------------+
Contoh Hasil 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 |
+--------------------------+------------+---------------+----------------------+
Untuk batasan default, periksa batasan dan batasan kunci asing, 4 byte terakhir dari nama yang dihasilkan secara otomatis adalah versi hexadecimal dari objectid dari kendala. Seperti objectid
yang dijamin unik namanya juga harus unik. Di Sybase juga menggunakan initabname_colname_objectid
Untuk batasan unik dan batasan kunci primer yang digunakan Sybase
tabname_colname_tabindid, di mana tabindid adalah rangkaian string ID tabel dan ID indeks
Ini juga akan menjamin keunikan.
SQL Server tidak menggunakan skema ini.
Dalam SQL Server 2008 dan 2017 menggunakan string 8 byte pada akhir nama sistem yang dihasilkan namun algoritma telah berubah tentang bagaimana 4 byte terakhir yang dihasilkan.
Pada tahun 2008, 4 byte terakhir mewakili penghitung bilangan bulat yang ditandatangani yang diimbangi object_id
oleh -16000057
dengan nilai negatif apa pun yang membungkus hingga maksimum yang ditandatangani. (Signifikansi 16000057
adalah bahwa ini adalah kenaikan yang diterapkan antara yang dibuat secara berturut-turutobject_id
). Ini masih menjamin keunikan.
Pada 2012 ke atas saya tidak melihat pola sama sekali antara object_id dari kendala dan integer yang diperoleh dengan memperlakukan 8 karakter terakhir dari nama sebagai representasi heksadesimal dari int yang ditandatangani.
Nama-nama fungsi di tumpukan panggilan pada 2017 menunjukkan bahwa itu sekarang membuat GUID sebagai bagian dari proses pembuatan nama (Pada 2008 saya tidak melihat menyebutkan MDConstraintNameGenerator
). Saya kira ini untuk memberikan beberapa sumber keacakan. Jelas itu tidak menggunakan keseluruhan 16 byte dari GUID dalam 4 byte yang mengubah kendala.
Saya kira algoritma baru dilakukan untuk beberapa alasan efisiensi dengan mengorbankan beberapa kemungkinan peningkatan tabrakan dalam kasus-kasus ekstrim seperti milik Anda.
Ini adalah kasus yang cukup patologis karena memerlukan awalan nama tabel dan nama kolom PK (sejauh ini mempengaruhi 8 karakter sebelum 8 akhir) untuk identik untuk puluhan ribu tabel sebelum menjadi kemungkinan tetapi dapat direproduksi cukup dengan mudah dengan di bawah ini.
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
Contoh berjalan pada SQL Server 2017 terhadap database yang baru dibuat gagal hanya dalam satu menit (setelah 50.931 tabel dibuat)
Msg 2714, Level 16, Negara 30, Jalur 15 Sudah ada objek bernama 'PK__abcdefgh__3BD019A8175067CE' dalam database. Msg 1750, Level 16, Negara 1, Jalur 15 Tidak dapat membuat batasan atau indeks. Lihat kesalahan sebelumnya.