Trong SQL Server, bạn có thể sử dụng sp_special_columns
hệ thống lưu trữ thủ tục để xác định một định danh duy nhất cho bảng. Cụ thể, nó trả về tập hợp các cột tối ưu xác định duy nhất một hàng trong bảng. Nó cũng trả về các cột được cập nhật tự động khi bất kỳ giá trị nào trong hàng được cập nhật bởi một giao dịch.
sp_special_columns
tương đương với SQLSpecialColumns trong ODBC.
Nếu không có cột nào có thể xác định duy nhất bảng, tập kết quả sẽ trống.
Cú pháp
Cú pháp như sau:
sp_special_columns [ @table_name = ] 'table_name' [ , [ @table_owner = ] 'table_owner' ] [ , [ @qualifier = ] 'qualifier' ] [ , [ @col_type = ] 'col_type' ] [ , [ @scope = ] 'scope' ] [ , [ @nullable = ] 'nullable' ] [ , [ @ODBCVer = ] 'ODBCVer' ] [ ; ]
@table_name
đối số là bắt buộc. Những người khác là tùy chọn. Xem tài liệu của Microsoft để biết giải thích chi tiết về từng đối số.
Ví dụ 1 - Cột Khóa Chính
Dưới đây là một ví dụ cơ bản về bảng có cột khóa chính được gọi là PersonId :
EXEC sp_special_columns Person;
Nó cũng có thể chạy như thế này:
EXEC sp_special_columns @table_name = 'Person';
Kết quả:
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+ | SCOPE | COLUMN_NAME | DATA_TYPE | TYPE_NAME | PRECISION | LENGTH | SCALE | PSEUDO_COLUMN | |---------+---------------+-------------+-------------+-------------+----------+---------+-----------------| | 1 | PersonId | 4 | int | 10 | 4 | 0 | 1 | +---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+
Trong trường hợp này, cột khóa chính được trả về. Tôi biết đây là cột khóa chính vì tôi đã tạo bảng bằng mã sau:
CREATE TABLE Person ( PersonId int primary key, PersonName varchar(500) );
Vì vậy, có vẻ như thủ tục được lưu trữ trên thực tế đã trả về cột tối ưu xác định duy nhất bảng này.
Ví dụ 2 - Cột DUY NHẤT
Bảng trong ví dụ này không có khóa chính nhưng có UNIQUE
ràng buộc.
Đây là mã được sử dụng để tạo bảng:
CREATE TABLE Event ( EventId int UNIQUE, EventName varchar(500) );
Vì vậy, bây giờ chúng ta hãy thực thi sp_special_columns
so với bảng đó:
EXEC sp_special_columns Event;
Kết quả:
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+ | SCOPE | COLUMN_NAME | DATA_TYPE | TYPE_NAME | PRECISION | LENGTH | SCALE | PSEUDO_COLUMN | |---------+---------------+-------------+-------------+-------------+----------+---------+-----------------| | 1 | EventId | 4 | int | 10 | 4 | 0 | 1 | +---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+
Trong trường hợp này, cột có UNIQUE
ràng buộc được coi là định danh duy nhất tối ưu.
Tuy nhiên, điều này không nhất thiết có nghĩa là bất kỳ cột bị ràng buộc bởi một UNIQUE
ràng buộc sẽ tự động đủ điều kiện làm định danh duy nhất. Kết quả có thể phụ thuộc vào cách xử lý các giá trị null.
Ví dụ 3 - Đối số @nullable
Bạn có thể sử dụng @nullable
để xác định xem các cột đặc biệt có thể chấp nhận giá trị null hay không.
Ở đây, tôi chạy lại cùng một mã, ngoại trừ lần này tôi sử dụng @nullable = 'O'
.
EXEC sp_special_columns Event, @nullable = 'O';
Kết quả:
(0 rows affected)
Ở đây nó đang sử dụng @nullable = 'U'
EXEC sp_special_columns Event, @nullable = 'U';
Kết quả:
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+ | SCOPE | COLUMN_NAME | DATA_TYPE | TYPE_NAME | PRECISION | LENGTH | SCALE | PSEUDO_COLUMN | |---------+---------------+-------------+-------------+-------------+----------+---------+-----------------| | 1 | EventId | 4 | int | 10 | 4 | 0 | 1 | +---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+
O
chỉ định các cột đặc biệt không cho phép giá trị rỗng. U
chỉ định các cột có thể null một phần. U
là giá trị mặc định.
Đây là những gì sẽ xảy ra nếu tôi tạo cột dưới dạng NOT NULL
:
DROP TABLE Event; CREATE TABLE Event ( EventId int NOT NULL UNIQUE, EventName varchar(500) ); EXEC sp_special_columns Event, @nullable = 'U'; EXEC sp_special_columns Event, @nullable = 'O';
Kết quả:
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+ | SCOPE | COLUMN_NAME | DATA_TYPE | TYPE_NAME | PRECISION | LENGTH | SCALE | PSEUDO_COLUMN | |---------+---------------+-------------+-------------+-------------+----------+---------+-----------------| | 1 | EventId | 4 | int | 10 | 4 | 0 | 1 | +---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+ (1 row affected) +---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+ | SCOPE | COLUMN_NAME | DATA_TYPE | TYPE_NAME | PRECISION | LENGTH | SCALE | PSEUDO_COLUMN | |---------+---------------+-------------+-------------+-------------+----------+---------+-----------------| | 1 | EventId | 4 | int | 10 | 4 | 0 | 1 | +---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+ (1 row affected)
Lần này cả O
và U
tạo ra cùng một kết quả.
Nếu bạn có một bảng với nhiều UNIQUE
các cột ràng buộc và một số cho phép giá trị rỗng trong khi những cột khác thì không, đối số này có thể có tác động đến việc một số được coi là giá trị nhận dạng duy nhất tối ưu. Xem Ví dụ 7 ở cuối bài viết này để biết ví dụ về ý tôi muốn nói.
Ví dụ 4 - Cột IDENTITY
Bảng trong ví dụ này không có khóa chính hoặc UNIQUE
nhưng nó có IDENTITY
cột.
Đây là mã được sử dụng để tạo bảng:
CREATE TABLE Product ( ProductId int IDENTITY, ProductName varchar(500) );
Vì vậy, bây giờ chúng ta hãy thực thi sp_special_columns
so với bảng đó:
EXEC sp_special_columns Product;
Kết quả:
(0 rows affected)
Vì vậy, có vẻ như IDENTITY
không đủ để nhận dạng duy nhất bảng này.
Ví dụ 5 - Khóa chính nhiều cột
Đây là một khóa có khóa chính nhiều cột. Trong trường hợp này, hai cột được sử dụng cho khóa chính.
Đây là mã được sử dụng để tạo bảng:
CREATE TABLE PersonProduct ( PersonId int, ProductId int, CONSTRAINT PK_PersonProduct PRIMARY KEY (PersonId, ProductId) );
Vì vậy, bây giờ chúng ta hãy thực thi sp_special_columns
so với bảng đó:
EXEC sp_special_columns PersonProduct;
Kết quả:
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+ | SCOPE | COLUMN_NAME | DATA_TYPE | TYPE_NAME | PRECISION | LENGTH | SCALE | PSEUDO_COLUMN | |---------+---------------+-------------+-------------+-------------+----------+---------+-----------------| | 1 | PersonId | 4 | int | 10 | 4 | 0 | 1 | | 1 | ProductId | 4 | int | 10 | 4 | 0 | 1 | +---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+
Ví dụ 6 - Khóa chính và Ràng buộc DUY NHẤT
Điều gì sẽ xảy ra nếu có khóa chính và một UNIQUE
ràng buộc trong cùng một bảng?
Hãy cùng tìm hiểu:
CREATE TABLE PersonEvent ( PersonEventId int UNIQUE, PersonId int, EventId int, CONSTRAINT PK_PersonEvent PRIMARY KEY (PersonId, EventId) );
Thực thi sp_special_columns
so với bảng đó:
EXEC sp_special_columns PersonEvent;
Kết quả:
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+ | SCOPE | COLUMN_NAME | DATA_TYPE | TYPE_NAME | PRECISION | LENGTH | SCALE | PSEUDO_COLUMN | |---------+---------------+-------------+-------------+-------------+----------+---------+-----------------| | 1 | PersonId | 4 | int | 10 | 4 | 0 | 1 | | 1 | EventId | 4 | int | 10 | 4 | 0 | 1 | +---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+
Khóa chính đã thắng.
Điều gì sẽ xảy ra nếu chúng ta chuyển đổi khóa chính và UNIQUE
các cột chính xung quanh?
Được rồi, hãy tạo toàn bộ bảng khác chỉ dành cho việc đó:
CREATE TABLE PersonEvent2 ( PersonEventId int PRIMARY KEY, PersonId int UNIQUE, EventId int UNIQUE );
Thực thi sp_special_columns
so với bảng đó:
EXEC sp_special_columns PersonEvent2;
Kết quả:
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+ | SCOPE | COLUMN_NAME | DATA_TYPE | TYPE_NAME | PRECISION | LENGTH | SCALE | PSEUDO_COLUMN | |---------+---------------+-------------+-------------+-------------+----------+---------+-----------------| | 1 | PersonEventId | 4 | int | 10 | 4 | 0 | 1 | +---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+
Vì vậy, khóa chính lại chiến thắng.
Ví dụ 7 - Rất nhiều Ràng buộc DUY NHẤT
Điều gì xảy ra nếu mọi cột có UNIQUE
ràng buộc?
CREATE TABLE Event2 ( EventId int UNIQUE, EventName varchar(500) UNIQUE, StartDate date UNIQUE, EndDate date UNIQUE );
Thực thi sp_special_columns
so với bảng đó:
EXEC sp_special_columns Event2;
Kết quả:
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+ | SCOPE | COLUMN_NAME | DATA_TYPE | TYPE_NAME | PRECISION | LENGTH | SCALE | PSEUDO_COLUMN | |---------+---------------+-------------+-------------+-------------+----------+---------+-----------------| | 1 | EndDate | -9 | date | 10 | 20 | NULL | 1 | +---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+
Nhưng hãy xem điều gì sẽ xảy ra nếu chúng ta đặt một trong các cột đó thành NOT NULL
, sau đó sử dụng @nullable = 'O'
:
DROP TABLE Event2; CREATE TABLE Event2 ( EventId int NOT NULL UNIQUE, EventName varchar(500) UNIQUE, StartDate date UNIQUE, EndDate date UNIQUE );
Thực thi sp_special_columns
với @nullable = 'O'
:
EXEC sp_special_columns Event2, @nullable = 'O';
Kết quả:
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+ | SCOPE | COLUMN_NAME | DATA_TYPE | TYPE_NAME | PRECISION | LENGTH | SCALE | PSEUDO_COLUMN | |---------+---------------+-------------+-------------+-------------+----------+---------+-----------------| | 1 | EventId | 4 | int | 10 | 4 | 0 | 1 | +---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+
Vì vậy, cột "not nullable" hiện được chọn làm giá trị nhận dạng duy nhất tối ưu.
Bây giờ chúng ta hãy thực thi sp_special_columns
với @nullable = 'U'
:
EXEC sp_special_columns Event2, @nullable = 'U';
Kết quả:
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+ | SCOPE | COLUMN_NAME | DATA_TYPE | TYPE_NAME | PRECISION | LENGTH | SCALE | PSEUDO_COLUMN | |---------+---------------+-------------+-------------+-------------+----------+---------+-----------------| | 1 | EndDate | -9 | date | 10 | 20 | NULL | 1 | +---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+
Bây giờ nó quay trở lại cột trước đó.