SQL Server có thể tạo xung đột trong các tên ràng buộc do hệ thống tạo không?
Điều này phụ thuộc vào loại ràng buộc và phiên bản của 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
Kết quả ví dụ 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 |
+--------------------------+-----------+---------------+----------------------+
Kết quả ví dụ 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 |
+--------------------------+------------+---------------+----------------------+
Đối với các ràng buộc mặc định, kiểm tra các ràng buộc và ràng buộc khóa ngoài, 4 byte cuối cùng của tên được tạo tự động là phiên bản thập lục phân của đối tượng của ràng buộc. Như objectid
được đảm bảo duy nhất, tên cũng phải là duy nhất. Trong Sybase cũng vậy những sử dụngtabname_colname_objectid
Đối với các ràng buộc duy nhất và các ràng buộc khóa chính, Sybase sử dụng
tabname_colname_tabindid, trong đó tabindid là một chuỗi nối của ID bảng và ID chỉ mục
Điều này cũng sẽ đảm bảo tính độc đáo.
SQL Server không sử dụng lược đồ này.
Trong cả SQL Server 2008 và 2017, nó sử dụng chuỗi 8 byte ở cuối tên được tạo bởi hệ thống, tuy nhiên thuật toán đã thay đổi như cách tạo ra 4 byte cuối cùng.
Trong năm 2008, 4 byte cuối cùng biểu thị một bộ đếm số nguyên đã ký được bù từ object_id
bởi -16000057
với bất kỳ giá trị âm nào được bao quanh đến int được ký tối đa. (Ý nghĩa của 16000057
việc này là mức tăng được áp dụng giữa các lần tạo liên tiếpobject_id
). Điều này vẫn đảm bảo tính độc đáo.
Vào năm 2012 trở đi, tôi không thấy bất kỳ mẫu nào ở giữa object_id của ràng buộc và số nguyên thu được bằng cách coi 8 ký tự cuối cùng của tên là biểu diễn thập lục phân của một int đã ký.
Các tên hàm trong ngăn xếp cuộc gọi năm 2017 cho thấy rằng bây giờ nó tạo GUID như một phần của quy trình tạo tên (Vào năm 2008 tôi không thấy đề cập đến MDConstraintNameGenerator
). Tôi đoán điều này là để cung cấp một số nguồn ngẫu nhiên. Rõ ràng là nó không sử dụng toàn bộ 16 byte từ GUID trong 4 byte đó thay đổi giữa các ràng buộc.
Tôi cho rằng thuật toán mới đã được thực hiện vì một số lý do hiệu quả với chi phí tăng khả năng va chạm trong các trường hợp cực đoan như của bạn.
Đây là một trường hợp bệnh lý vì nó yêu cầu tiền tố tên bảng và tên cột của PK (trong trường hợp này ảnh hưởng đến 8 ký tự trước 8 ký tự cuối cùng) giống hệt nhau cho hàng chục nghìn bảng trước khi có thể xảy ra nhưng có thể được sao chép hoàn toàn dễ dàng với những điều dưới đây
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
Một ví dụ chạy trên SQL Server 2017 đối với cơ sở dữ liệu mới được tạo không thành công chỉ sau hơn một phút (sau khi 50.931 bảng đã được tạo)
Msg 2714, Cấp 16, Bang 30, Dòng 15 Đã có một đối tượng có tên 'PK__abcdefgh__3BD019A8175067CE' trong cơ sở dữ liệu. Msg 1750, Cấp 16, Trạng thái 1, Dòng 15 Không thể tạo ràng buộc hoặc chỉ mục. Xem các lỗi trước.