在SQL Server中,實際上外鍵值可不可以為空(NULL),和外鍵關系是不是強制約束無關。
我們先在SQL Server數據庫中建立兩張表People和Car,一個People可以有多個Car,所以這兩張表是一對多關系。
建立表
People建表語句:
CREATE TABLE [dbo].[People]( [ID] [int] NOT NULL, [Name] [nvarchar](50) NULL, [Age] [int] NULL, [Sex] [nvarchar](50) NULL, CONSTRAINT [PK_People] PRIMARY KEY CLUSTERED ( [ID] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO
其中列ID是People表的主鍵
Car建表語句:
CREATE TABLE [dbo].[Car]( [ID] [int] NOT NULL, [Brand] [nvarchar](50) NULL, [PeopleID] [int] NULL, CONSTRAINT [PK_Car] PRIMARY KEY CLUSTERED ( [ID] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO ALTER TABLE [dbo].[Car] WITH CHECK ADD CONSTRAINT [FK_Car_People] FOREIGN KEY([PeopleID]) REFERENCES [dbo].[People] ([ID]) GO ALTER TABLE [dbo].[Car] CHECK CONSTRAINT [FK_Car_People] GO
其中列ID是Car表的主鍵,此外列PeopleID是Car表的外鍵,其關聯People表的主鍵ID。我們還為People表和Car表之間的外鍵關系[FK_Car_People]設置了強制約束(CHECK)。
注意上面外鍵約束[FK_Car_People]中CHECK關鍵字代表是強制約束,而如果使用NOCHECK關鍵字代表是非強制約束。
外鍵關系語法擴展
建立外鍵關系[FK_Car_People]為強制約束(CHECK)的SQL語句如下:
--下面CHECK關鍵字表示建立外鍵關系時就開啟強制約束 ALTER TABLE [dbo].[Car] WITH CHECK ADD CONSTRAINT [FK_Car_People] FOREIGN KEY([PeopleID]) REFERENCES [dbo].[People] ([ID]) GO --注意上面建立外鍵關系[FK_Car_People]后,下面這句ALTER TABLE語句也不能少 ALTER TABLE [dbo].[Car] CHECK CONSTRAINT [FK_Car_People] GO
建立外鍵關系[FK_Car_People]為非強制約束(NOCHECK)的SQL語句如下:
--下面NOCHECK關鍵字表示建立外鍵關系時不開啟強制約束,也就是非強制約束 ALTER TABLE [dbo].[Car] WITH NOCHECK ADD CONSTRAINT [FK_Car_People] FOREIGN KEY([PeopleID]) REFERENCES [dbo].[People] ([ID]) GO --注意上面建立外鍵關系[FK_Car_People]后,下面這句ALTER TABLE語句也不能少 ALTER TABLE [dbo].[Car] NOCHECK CONSTRAINT [FK_Car_People] GO
上面建立好外鍵關系[FK_Car_People]后,可以通過下面的語句再將外鍵關系[FK_Car_People]改為強制(CHECK)或非強制(NOCHECK)約束,其實就是刪除外鍵關系[FK_Car_People]后再重建:
更改外鍵關系[FK_Car_People]為強制約束(CHECK)的SQL語句如下:
--刪除外鍵關系[FK_Car_People] ALTER TABLE [dbo].[Car] DROP CONSTRAINT [FK_Car_People] --下面CHECK關鍵字表示建立外鍵關系時就開啟強制約束 ALTER TABLE [dbo].[Car] WITH CHECK ADD CONSTRAINT [FK_Car_People] FOREIGN KEY([PeopleID]) REFERENCES [dbo].[People] ([ID]) GO --注意上面建立外鍵關系[FK_Car_People]后,下面這句ALTER TABLE語句也不能少 ALTER TABLE [dbo].[Car] CHECK CONSTRAINT [FK_Car_People] GO
更改外鍵關系[FK_Car_People]為非強制約束(NOCHECK)的SQL語句如下:
--刪除外鍵關系[FK_Car_People] ALTER TABLE [dbo].[Car] DROP CONSTRAINT [FK_Car_People] --下面NOCHECK關鍵字表示建立外鍵關系時不開啟強制約束,也就是非強制約束 ALTER TABLE [dbo].[Car] WITH NOCHECK ADD CONSTRAINT [FK_Car_People] FOREIGN KEY([PeopleID]) REFERENCES [dbo].[People] ([ID]) GO --注意上面建立外鍵關系[FK_Car_People]后,下面這句ALTER TABLE語句也不能少 ALTER TABLE [dbo].[Car] NOCHECK CONSTRAINT [FK_Car_People] GO
在本例中,外鍵關系[FK_Car_People]應該是強制約束(CHECK)的,所以下面我們來為People表和Car表插入數據。
插入數據
下面我們為People表插入兩條數據:
INSERT INTO [dbo].[People](ID,Name,Age,Sex) VALUES (1,N'張三',25,N'男'), (2,N'李四',26,N'女');
查詢結果如下:
然后我們為Car表插入五條數據:
INSERT INTO [dbo].[Car](ID,Brand,PeopleID) VALUES (1,N'奔馳',1), (2,N'寶馬',1), (3,N'大眾',2), (4,N'別克',NULL), (5,N'豐田',NULL);
注意我們在最后兩條數據"別克"和"豐田"中,插入了空值(NULL)到Car表的外鍵列PeopleID。但是語句並沒有報錯,五條數據都被成功插入了,查詢結果如下:
所以Car表的外鍵列PeopleID能不能為空(NULL),和其外鍵關系[FK_Car_People]是不是強制約束(CHECK)無關,它只和Car表允不允許外鍵列PeopleID為空(NULL)相關。
現在我們把Car表的外鍵列PeopleID改為不允許為空(NULL),然后再次插入前面的五條數據:
DELETE FROM [dbo].[Car] ALTER TABLE [dbo].[Car] ALTER COLUMN [PeopleID] INT NOT NULL INSERT INTO [dbo].[Car](ID,Brand,PeopleID) VALUES (1,N'奔馳',1), (2,N'寶馬',1), (3,N'大眾',2), (4,N'別克',NULL), (5,N'豐田',NULL);
這時插入語句就會報錯了,因為此時Car表的外鍵列PeopleID不能為空(NULL):
所以SQL Server中的外鍵關系強制約束,約束的實際上是外鍵的非空值,而外鍵的空值(NULL)並不受外鍵強制約束。