复杂的检查约束?

Posted

技术标签:

【中文标题】复杂的检查约束?【英文标题】:Complex Check Constraint? 【发布时间】:2014-02-24 21:45:58 【问题描述】:

我有一个客户表,它通过中间的 CustomerAddress 表链接到地址表。这意味着一个客户可以有很多地址,一个地址可以有很多客户。 (这是必要的,因为我们将配偶和子女视为单独的客户,每个人都可以有送货、工作、账单和其他地址)。

我希望客户能够指定首选地址。

我的想法是在客户表中创建一个链接到 CustomerAddress 记录的新列。

我的问题是 - 如何确保所选的首选地址是客户地址之一?

我的想法是在 customers.preferredAddress 字段上设置一个检查约束,检查给定的 CustomerAddress 以查看该记录的客户 ID 是否与正在更新的客户匹配。

这可能吗?我只使用过检查约束来检查简单的东西,比如 (Value > 0) 等。

感谢您的帮助

【问题讨论】:

为什么在客户桌上?客户地址记录上的新列是“首选地址”和一个简单的 y/n(或位)来定义是或否(或 null 表示否)怎么样?如果它在 customeraddress 表中,则强制执行它是客户地址之一的关系。 但是我怎样才能阻止一位客户拥有多个首选地址? 【参考方案1】:

编写一个用于验证地址所有权的 UDF,然后从检查约束中引用该 UDF。

CREATE FUNCTION dbo.fnIsAddressOwner (
  @CustomerId int,
  @AddressId int
)
RETURNS tinyint
AS
BEGIN
  DECLARE @Result tinyint
  IF EXISTS(SELECT * FROM CustomerAddresses WHERE CustomerId=@CustomerId and AddressId=@AddressId)
    SET @Result= 1
  ELSE 
    SET @Result= 0
  RETURN @Result
END


CREATE TABLE Customers (
  CustomerId int,
  PreferredAddressId int,
  CONSTRAINT ckPreferredAddressId CHECK (
    dbo.fnIsAddressOwner(CustomerId, PreferredAddressId) = 1)
  )
)

【讨论】:

如果检查约束对您不起作用,那么您也可以在触发器中执行检查。如果验证失败,则回滚事务。 当然,上面没有任何内容阻止UPDATE CustomerAddresses set CustomerId = <new value> where CustomerId = <old value>,现在违反了“约束”。

以上是关于复杂的检查约束?的主要内容,如果未能解决你的问题,请参考以下文章

如果我有 IBOutlet 进行约束,复杂 UIView 的布局会有所不同

Trigger 触发器

数据库 MySQL进阶(复杂的增删改查)

JPA 2 向表添加引用约束使标准查询与延迟获取复杂化,需要建议

Oracle-视图,约束

如何在情节提要失败的情况下使用大量表格视图单元格和自动布局约束来布局复杂视图