如何对外键引用字段设置数据库完整性检查
我有四个这样的数据库表:
预订
ID_Book |ID_Company|说明图书扩展
ID_BookExtension | ID_书| ID_折扣折扣
ID_折扣|描述 | ID_公司公司
ID_公司 |说明
任何通过外键的 BookExtension
记录都间接指向两个不同的 ID_Company
字段:
BookExtension.ID_Book 引用包含 Book.ID_Company 的 Book 记录
BookExtension.ID_Discount 引用包含 Discount.ID_Company 的 Discount 记录
是否可以在 Sql Server 中强制要求 BookExtension
中的任何新记录必须具有 Book.ID_Company = Discount.ID_Company
?
简而言之,我希望以下查询必须返回 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
记录引用 Company
的 Book
记录和另一个 Discount
记录不同的公司
!
I have four Database Tables like these:
Book
ID_Book |ID_Company|DescriptionBookExtension
ID_BookExtension | ID_Book| ID_DiscountDiscount
ID_Discount | Description | ID_CompanyCompany
ID_Company | Description
Any BookExtension
record via foreign keys points indirectly to two different ID_Company
fields:
BookExtension.ID_Book references a Book record that contains a Book.ID_Company
BookExtension.ID_Discount references a Discount record that contains a Discount.ID_Company
Is it possible to enforce in Sql Server that any new record in BookExtension
must have Book.ID_Company = Discount.ID_Company
?
In a nutshell I want that the following Query must return 0 record!
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
or, in plain English:
I don't want that a BookExtension
record references a Book
record of a Company
and a Discount
record of another different Company
!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
除非我误解了您的意图,否则您将使用的 SQL 语句的一般形式是
假设现有数据已经符合新的约束。如果现有数据不符合要求,您可以修复数据(假设需要修复),也可以通过检查 ID_FooExtension 的值来限制新约束的范围(可能)。 (假设您可以通过 ID_FooExtension 的值识别“新”行。)
稍后。 。 .
谢谢,我确实误解了你的情况。
据我所知,您无法在 SQL Server 中按照您想要的方式强制执行该约束,因为它不允许在 CHECK 约束内进行 SELECT 查询。 (在 SQL Server 2008 中我对此可能是错误的。)常见的解决方法是将 SELECT 查询包装在函数中,然后调用该函数,但根据我所了解的情况,这并不可靠。
不过,您可以做到这一点。
(ID_图书、ID_公司)。它的一部分看起来像
UNIQUE (ID_Book, ID_Company)
。图书扩展--Book_ID_Company 和
折扣_ID_公司。
在 BookExtension 中。你想要
图书扩展名(ID_Book,
Book_ID_Company) 参考
书籍(ID_Book、ID_Company)。外键的类似更改
参考折扣。
现在您可以添加检查约束来保证 BookExtension.Book_ID_Company 与 BookExtension.Discount_ID_Company 相同。
Unless I've misunderstood your intent, the general form of the SQL statement you'd use is
That assumes existing data already conforms to the new constraint. If existing data doesn't conform, you can either fix the data (assuming it needs fixing), or you can limit the scope (probably) of the new constraint by also checking the value of ID_FooExtension. (Assuming you can identify "new" rows by the value of ID_FooExtension.)
Later . . .
Thanks, I did indeed misunderstand your situation.
As far as I know, you can't enforce that constraint the way you want to in SQL Server, because it doesn't allow SELECT queries within a CHECK constraint. (I might be wrong about that in SQL Server 2008.) A common workaround is to wrap a SELECT query in a function, and call the function, but that's not reliable according to what I've learned.
You can do this, though.
(ID_Book, ID_Company). Part of it will look like
UNIQUE (ID_Book, ID_Company)
.BookExtension--Book_ID_Company and
Discount_ID_Company.
in BookExtension. You want
BookExtension (ID_Book,
Book_ID_Company) to reference
Book (ID_Book, ID_Company). Similar change for the foreign key
referencing Discount.
Now you can add a check constraint to guarantee that BookExtension.Book_ID_Company is the same as BookExtension.Discount_ID_Company.
我不确定这有多高效,但您也可以使用索引视图来实现这一点。它需要一个包含 2 行的辅助表,因为索引视图中不允许使用 CTE 和 UNION。
然后是视图定义
以及视图上的唯一索引
I'm not sure how [in]efficient this would be but you could also use an indexed view to achieve this. It needs a helper table with 2 rows as CTEs and
UNION
are not allowed in indexed views.Then the view definition
And a unique index on the View