patternsqlMinor
Maintaining integrity between 3 tables when reference could be through or direct
Viewed 0 times
tablesreferenceintegritythroughcoulddirectbetweenwhenmaintaining
Problem
Say we have the following 3 tables:
Is there a way from the DB to prevent a user from having mismatched Country/Region while still allowing one or both to be NULL? For example, the query
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 | EuropeIs there a way from the DB to prevent a user from having mismatched Country/Region while still allowing one or both to be NULL? For example, the query
UPDATE tUsers SET regionID=4 WHERE ID = 3 would fail since Bob's country is China which is not in region Europe.Solution
3 foreign keys version
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 tUsersCode Snippets
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 tUsersContext
StackExchange Database Administrators Q#139042, answer score: 7
Revisions (0)
No revisions yet.