我有四个这样的数据库表:
图书
ID_Book | ID_Company |描述BookExtension
ID_BookExtension | ID_Book | ID_Discount折扣
ID_Discount |说明| ID_Company公司
ID_Company |说明
通过外键的任何BookExtension
记录间接指向两个不同的ID_Company
字段:
BookExtension.ID_Book引用包含Book.ID_Company的Book记录 BookExtension.ID_Discount引用包含Discount.ID_Company
的折扣记录
是否可以在Sql Server中强制BookExtension
中的任何新记录必须Book.ID_Company = Discount.ID_Company
?
简而言之,我希望以下Query必须返回0记录!
SELECT count(*) from BookExtension
INNER JOIN Book ON BookExstension.ID_Book = Book.ID_Book
INNER JOIN Discount ON BookExstension.ID_Discount = Discount.ID_Discount
WHERE Book.ID_Company <> Discount.ID_Company
或用简单的英语:
我不希望BookExtension
条记录引用Book
的{{1}}条记录以及另一条Company
的{{1}}条记录!
答案 0 :(得分:2)
除非我误解了您的意图,否则您使用的SQL语句的一般形式是
ALTER TABLE FooExtension
ADD CONSTRAINT your-constraint-name
CHECK (ID_Foo = ID_Bar);
假设现有数据已经符合新约束。如果现有数据不符合,您可以修复数据(假设需要修复),或者您也可以通过检查ID_FooExtension的值来限制新约束的范围(可能)。 (假设您可以通过ID_FooExtension的值识别“新”行。)
稍后。 。 强>
谢谢,我确实误解了你的情况。
据我所知,您不能以您希望的方式在SQL Server中强制执行该约束,因为它不允许在CHECK约束内进行SELECT查询。 (我在SQL Server 2008中可能错了。)一个常见的解决方法是将SELECT查询包装在一个函数中,并调用该函数,但根据我所学到的,这是不可靠的。
你可以这样做。
UNIQUE (ID_Book, ID_Company)
。现在您可以添加一个检查约束,以保证BookExtension.Book_ID_Company与BookExtension.Discount_ID_Company相同。
答案 1 :(得分:2)
我不确定这会有多高效,但您也可以使用索引视图来实现这一目标。它需要一个包含2行作为CTE的帮助器表,并且在索引视图中不允许UNION
。
CREATE TABLE dbo.TwoNums
(
Num int primary key
)
INSERT INTO TwoNums SELECT 1 UNION ALL SELECT 2
然后是视图定义
CREATE VIEW dbo.ConstraintView
WITH SCHEMABINDING
AS
SELECT 1 AS Col FROM dbo.BookExtension
INNER JOIN dbo.Book ON dbo.BookExtension.ID_Book = Book.ID_Book
INNER JOIN dbo.Discount ON dbo.BookExtension.ID_Discount = Discount.ID_Discount
INNER JOIN dbo.TwoNums ON Num = Num
WHERE dbo.Book.ID_Company <> dbo.Discount.ID_Company
视图上的唯一索引
CREATE UNIQUE CLUSTERED INDEX [uix] ON [dbo].[ConstraintView]([Col] ASC)