当引用可以通过或直接引用时保持 3 个表之间的完整性

Dav*_*key 4 database-design sql-server data-integrity

假设我们有以下 3 个表:

tUsers (ID, name, countryID, regionID)
------
1  |  Joe  |  1   |  1
2  |  Sue  | NULL |  2
3  |  Bob  |  2   |  NULL
4  |  Amy  | NULL |  NULL

tCountries (ID, name, regionID)
------
1  |  USA   |  1
2  |  China |  3

tRegions (ID, name)
------
1  |  North America
2  |  Central America
3  |  East Asia
4  |  Europe
Run Code Online (Sandbox Code Playgroud)

DB 是否有一种方法可以防止用户在国家/地区不匹配的同时仍然允许一个或两个为 NULL?例如,查询UPDATE tUsers SET regionID=4 WHERE ID = 3将失败,因为 Bob 的国家是中国而不是欧洲地区。

Ser*_*erg 7

3个外键版本

create table tRegions (
  ID int not null primary key, 
  name  varchar(20)
); 

create table tCountries (
  ID int not null primary key, 
  name varchar(20), 
  regionID int, 
  --any superset of PK is undoubtly UNIQUE
  constraint cu1 unique (ID, regionID),
  foreign key (regionID) references tRegions(ID)
  );

create table tUsers (
 ID int not null primary key, 
 name varchar(20), 
 countryID int ,
 regionID int,
 foreign key (regionID) references tRegions(ID),
 foreign key (countryID) references tCountries(ID),
 foreign key (countryID,regionID) references tCountries(ID,regionID )
)

insert tRegions (ID, name)
values
(1,'North America'),
(2,'Central America'),
(3,'East Asia'),
(4,'Europe') 

insert tCountries(ID, name, regionId)
values
(1,'USA',1),
(2,'China',3)

insert tUsers (ID, name, countryID, regionId)
values
(1,'Joe', 1  ,1),
(2,'Sue',NULL,2),
(3,'Bob', 2  ,NULL),
(4,'Amy',NULL,NULL)

go
--OK
update tUsers set RegionId=3
where ID=3
select * from tUsers
go
--fails
update tUsers set CountryId=2
where ID=2
select * from tUsers
Run Code Online (Sandbox Code Playgroud)