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

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

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

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

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

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

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

感谢您的帮助

【问题讨论】:

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

标签: sql sql-server sql-server-2012 check-constraint


【解决方案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>,现在违反了“约束”。
猜你喜欢
  • 2022-11-17
  • 1970-01-01
  • 2018-03-11
  • 2020-08-15
  • 1970-01-01
  • 2022-08-22
  • 1970-01-01
  • 2011-01-28
  • 2023-03-13
相关资源
最近更新 更多