5

我有一张桌子,ProductSupportArticles:

ProductSupportArticleID int NOT NULL <primary key>
ParentArticleID int NULL
ProductID int NOT NULL
Title varchar(100) NOT NULL
Content varchar(MAX) NOT NULL

ProductID 是 Products.ID 的外键,ParentArticleID 是同一个表 ProductSupportArticles.ProductSupportArticleID 的外键。我有一个检查约束 ProductSupportArticleID != ParentArticleID 以便文章不能是它自己的父级。

但是,与特定产品相关的支持文章不应成为与不同产品相关的文章的父项或子项。如何添加检查约束或类似的说法:(ProductID = (SELECT ProductID FROM ProductSupportArticles P WHERE ParentArticleID = P.ProductSupportArticleID))

或者我应该如何以不同的方式实现我的表?

4

2 回答 2

5
  1. 在 (ProductSupportArticleID, ProductID) 上创建一个唯一约束。
  2. 让 FK 将 (ParentArticleID, ProductID) 引用到 (ProductSupportArticleID, ProductID)

警告:通过包装在 CHECK 约束中的 UDF 执行业务规则有多个漏洞。例如,对于多行修改,它们可能会给出误报和误报。他们也很慢。

于 2011-03-21T01:32:06.407 回答
2

工作样本

示例表:

create table products (productid int primary key)
insert products select 1
insert products select 2
GO

create table ProductSupportArticles (
ProductSupportArticleID int NOT NULL primary key,
ParentArticleID int NULL references ProductSupportArticles(ProductSupportArticleID),
ProductID int NOT NULL references products (productid),
Title varchar(100) NOT NULL,
Content varchar(MAX) NOT NULL
)
GO

支持功能

create function dbo.getProductSupportArticleParent(@ParentArticleID int)
returns int
with returns null on null input
as
begin
return (select ProductID from ProductSupportArticles where ProductSupportArticleID = @ParentArticleID)
end
GO

约束

alter table ProductSupportArticles add check(
    ParentArticleID is null or
    dbo.getProductSupportArticleParent(ParentArticleID) = ProductID)
GO

测试

insert ProductSupportArticles select 1,null,1,3,4
insert ProductSupportArticles select 2,null,1,3,4
insert ProductSupportArticles select 3,null,2,3,4
insert ProductSupportArticles select 4,1,1,3,4

好的,到目前为止,下一个打破了它,因为 5 是 1 的父级,它属于产品 1。

insert ProductSupportArticles select 5,1,2,3,4


编辑

亚历克斯指出了一个有效的缺陷。为了涵盖这种情况,您需要一个 UPDATE 触发器,它将对记录的 ProductID 的更改传播到所有子(和后代)记录。这将是一个简单的触发器,所以我不会在这里提供代码。

于 2011-03-21T00:33:29.463 回答