Как ссылаться на другие таблицы в проверочных ограничениях? - PullRequest
5 голосов
/ 21 марта 2011

У меня есть таблица, 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))

Или как мне по-другому реализовать мои таблицы?

Ответы [ 2 ]

5 голосов
/ 21 марта 2011
  1. Создание УНИКАЛЬНОГО ограничения для (ProductSupportArticleID, ProductID).
  2. Пусть FK ссылается (ParentArticleID, ProductID) на (ProductSupportArticleID, ProductID)

Предупреждение: принудительное выполнениебизнес-правила через UDF, заключенные в ограничения CHECK, имеют несколько лазеек.Например, они могут давать ложные срабатывания и ложные отрицания для многорядных модификаций.Также они очень медленные.

2 голосов
/ 21 марта 2011

Рабочий образец

Образцы таблиц:

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


EDIT

Алекс указал на допустимый недостаток. Чтобы охватить этот сценарий, вам понадобится триггер UPDATE, который распространит изменения в ProductID записи на все дочерние (и дочерние) записи. Это будет простой триггер, поэтому я не буду приводить здесь код.

...