Constraint

創建主鍵和外鍵時,CONSTRAINT 關鍵字是可選的嗎?

  • December 11, 2020

創建新表時,有時範例會顯示使用CONSTRAINT關鍵字定義的主鍵和外鍵,而有時則不顯示CONSTRAINT關鍵字。使用CONSTRAINT關鍵字為約束命名的唯一原因是什麼?還是有其他原因您會選擇使用或不使用此關鍵字?

範例 1(沒有關鍵字):

CREATE TABLE Persons (
   ID int NOT NULL,
   LastName varchar(255) NOT NULL,
   FirstName varchar(255),
   Age int,
   PRIMARY KEY (ID)
);

範例 2(使用關鍵字):

CREATE TABLE Persons (
   ID int NOT NULL,
   LastName varchar(255) NOT NULL,
   FirstName varchar(255),
   Age int,
   CONSTRAINT PK_Person PRIMARY KEY (ID)
);

除了分配一個指定的約束名稱之外,DBMS 對這兩個範例的看法是否不同?我特別考慮 SQL Server、Oracle、MySQL 和 PostgreSQL。

對於 SQL Server,Microsoft 文件非常清楚地說明了這一點(粗體是我的格式):

CONSTRAINT

是一個可選關鍵字,指示 PRIMARY KEY、NOT NULL、UNIQUE、FOREIGN KEY 或 CHECK 約束定義的開始。

因此,您無需CONSTRAINT xxxCREATE TABLE聲明中指定。

但是請注意,**如果您不指定約束名稱,**如果您包含約束定義,SQL Server 將為您生成一個。這個例子展示了創建一個PRIMARY KEY約束,但沒有命名它。

CREATE TABLE dbo.ConstraintTest
(
   ConstraintTest_ID int NOT NULL
       PRIMARY KEY CLUSTERED
) ON [PRIMARY];

SELECT o_parent.name
   , o.name
FROM sys.key_constraints kc
   INNER JOIN sys.objects o ON kc.object_id = o.object_id
   INNER JOIN sys.objects o_parent on kc.parent_object_id = o_parent.object_id
WHERE o_parent.name = 'ConstraintTest';

DROP TABLE dbo.ConstraintTest

SELECT上面語句的結果:

+----------------+--------------------------------+
| 姓名 | 姓名 |
+----------------+--------------------------------+
| 約束測試 | PK__Constrai__471ED41490593601 |
+----------------+--------------------------------+

這導致了命名所有約束的普遍接受的最佳實踐,如:

CREATE TABLE dbo.ConstraintTest
(
   ConstraintTest_ID int NOT NULL
       CONSTRAINT PK_ConstraintTest
       PRIMARY KEY CLUSTERED
) ON [PRIMARY];

與往常一樣,這裡的“It Depends™”時刻是針對臨時表的;我們幾乎從不指定應用於臨時表的約束的名稱,因為我們希望它們是唯一的,並且允許 SQL Server 命名它們以確保它們實際上是唯一的。如果您確實指定了約束名稱,那麼在任何給定時間只能存在該臨時表的一個副本;嘗試創建多個臨時表副本將導致錯誤:

消息 2714,級別 16,狀態 5,第 19 行

數據庫中已經有一個名為“PK_ConstraintTest”的對象。

消息 1750,級別 16,狀態 0,第 19 行

無法創建約束。請參閱以前的錯誤。

您可以輕鬆地將UNIQUE約束添加到沒有名稱的現有列;如:

ALTER TABLE dbo.Blah
ADD UNIQUE (SomeColumn);

在您添加到問題的範例中,唯一的區別是您沒有指定約束名稱,從而允許 SQL Server 為約束生成名稱。除了約束的名稱之外,這兩個表之間沒有區別。

引用自:https://dba.stackexchange.com/questions/171434