在SQL Server 2012中保持循环引用中的数据完整性

时间:2013-03-09 12:20:30

标签: sql sql-server tsql constraints data-integrity

假设我们有三个表Customer,City和Country

国家/地区表:

  • ID(PK)
  • 名称。

城市表:

  • ID(PK)
  • CountryID(FK)
  • 名称

客户表:

  • ID(PK)
  • CountryID(FK)(NULL)
  • CityID(FK)(NULL)
  • 名称 等......

您可以猜测客户可能已经或可能没有分配CityID或CountryID。

那么确保在插入/更新客户时我们最终不会使用不在指定国家/地区的城市的最佳方式是什么?

2 个答案:

答案 0 :(得分:1)

我不确定这是最好的方法,但你可以添加一个函数并在你的检查约束中使用它:

CREATE FUNCTION CheckCityInCountry(@CityID int, @CountryID int)
RETURNS int
AS 
BEGIN
   DECLARE @retval int
   SELECT @retval = COUNT(*) 
     FROM Cityies CI inner join Countries CO on (CI.CountryID, CO.ID)
     WHERE CO.CountryID = @CountryID and CityID = @CityID
   RETURN @retval
END;
GO

如果城市在一个国家,此功能将返回1,否则返回0。

然后使用该函数添加检查约束:

ALTER TABLE Customers
ADD CONSTRAINT chk_CheckCityInCountry CHECK (
   CityID is null OR
   dbo.CheckCityInCountry(CityID,CountryID) >= 1
);
GO

答案 1 :(得分:0)

将国家和城市表格中的FK关系设置为

将City表更改为CountryID,CityID的复合PK FK关系必须引用两者。

FK未在null上强制执行。

有一点需要注意的是,您可以输入带有空国家/地区的错误CityID,因为此时FK都不会被强制执行 但我认为可以使用CHECK CONSTRAINT强制执行。

ALTER TABLE dbo.CustomerCountyCity ADD CONSTRAINT CK_CustomerCountyCity
    CHECK (CountryID is not null OR CityID is Null)