假设我有以下表格:
CREATE TABLE Products
(
ProdID INT PRIMARY KEY IDENTITY(100,5),
ProdName VARCHAR(20)
)
然后插入一些行:
INSERT INTO Products VALUES ('Coat Rack') --Will be given a ProdID of 100
INSERT INTO Products VALUES ('Coffee Table') --Will be given a ProdID of 105
然后我创建另一个名为Orders的表,它有一个FK约束:
CREATE TABLE Orders
(
OrderID INT PRIMARY KEY IDENTITY(800,2),
ProductID INT DEFAULT 0,
CONSTRAINT fk_ProdID FOREIGN KEY(ProductID) REFERENCES Products(ProdID) ON DELETE SET DEFAULT
)
注意ProductID列的默认值是0,并且有一个FK约束指定了ON DELETE SET default设置。
插入一行:
INSERT INTO Orders VALUES (105) --Row references the "Coffee Table" product.
如果我试图删除产品"咖啡桌";从Products表中,我得到一条消息,说该产品不能删除,因为它在Orders表中被引用。我理解它是,但我期望FK约束只是允许删除行,然后在引用行中放置0。0当然是引用列(ProductID)的默认值,FK约束指定ON DELETE SET default。
那么使用ON DELETE SET DEFAULT,默认值还需要存在于被引用的表中吗?
如果是这样的话,我觉得有点奇怪。有人可能想要创建一个"假人"。行,并将默认值设置为该虚拟行使用的任何ID。这样,如果我们删除一个产品,任何引用行都将指向该虚拟产品,而不是实际产品
根据文档
设置默认
当父表中相应的行被删除时,组成外键的所有值都被设置为它们的默认值。要执行此约束,所有外键列必须具有默认定义。如果列是可空的,并且没有显式的默认值设置,NULL将成为该列的隐式默认值。
https://learn.microsoft.com/en-us/sql/t-sql/statements/alter-table-table-constraint-transact-sql?view=sql-server-ver15
它没有很好地解释的是默认值必须存在在父表中。如果没有,则得到违反约束的错误。
基于您的示例向您展示的方法
CREATE TABLE Products
(
ProdID INT PRIMARY KEY IDENTITY(100,5),
ProdName VARCHAR(20)
)
CREATE TABLE Orders
(
OrderID INT PRIMARY KEY IDENTITY(800,2),
ProductID INT DEFAULT 0,
CONSTRAINT fk_ProdID FOREIGN KEY(ProductID) REFERENCES Products(ProdID)
ON DELETE SET DEFAULT
)
INSERT INTO Products VALUES ('Coat Rack') --Will be given a ProdID of 100
INSERT INTO Products VALUES ('Coffee Table') --Will be given a ProdID of 105
SET IDENTITY_INSERT Products ON; -- Enable to insert default dummy product
INSERT INTO Products (ProdID, ProdName) VALUES ( 0 , 'Dummy') -- Insert dummy product
INSERT INTO Orders VALUES (105) --Row references the "Coffee Table" product.
DELETE FROM Orders where ProductID = 105
dbfiddle
中代码的完整演示,db<的在小提琴