是否可以强制基于数据库完整性的间接关系
Is it possible to enforce database integrity based indirect relationship
我有 Thing
个 Type
。我还有这些 Token
与 Type
相关联。现在我想说一个Thing
有Token
的组合。可能的 table 表示是:
| Thing | | Type | | Token | | TypeToken | | ThingToken |
|-------| |------| |-------| |-----------| |------------|
| Id | | Id | | Id | | TypeId | | ThingId |
| Type | |------| |-------| | TokenId | | TokenId |
|-------| |-----------| |------------|
为了数据库的完整性,我想强制要求 Thing
只能有 Token
,前提是它们之前与 Type
相关联。我最好的选择是什么?
是的,你可以!这是您需要的示例,
CREATE TABLE Foo (
FooId INT
, Value VARCHAR(10)
)
CREATE TABLE Bar (
BarId INT
, FooId INT
, Value VARCHAR(10)
)
GO
CREATE FUNCTION CheckFooExistsOnBar
(
@FooId INT
)
RETURNS BIT
AS
BEGIN
DECLARE @Response BIT = 0;
IF EXISTS (SELECT * FROM Bar WHERE FooId = @FooId)
SET @Response = 1;
RETURN @Response
END
GO
ALTER TABLE Foo
ADD CONSTRAINT CHK_FooId_Foo
CHECK (dbo.CheckFooExistsOnBar(FooId) = 1)
INSERT INTO Foo (FooId, Value) VALUES (1, '')
查看more
一种方法是将 TypeId 添加到 ThingToken table,这样您就可以在外键中使用它。您还需要对 Thing 进行额外的唯一约束,但您可以将其放在 (TypeId,Id) 上,因此它对于按 TypeId 进行查找也很有用,并且在物理上与仅 (TypeId) 上的非聚集索引相同。
EG:
use tempdb
go
drop table if exists ThingToken
drop table if exists TypeToken
drop table if exists Token
drop table if exists Thing
drop table if exists Type
--| Thing | | Type | | Token | | TypeToken | | ThingToken |
--|-------| |------| |-------| |-----------| |------------|
--| Id | | Id | | Id | | TypeId | | ThingId |
--| Type | |------| |-------| | TokenId | | TokenId |
--|-------| |-----------| |------------|
create table Type(Id int primary key)
create table Token(Id int primary key)
create table TypeToken
(
TypeId int not null references Type,
TokenId int not null references Token,
constraint pk_TypeToken
primary key (TypeId,TokenId)
)
create table Thing
(
Id int not null primary key,
TypeId int references Type,
constraint ak_Thing
unique (TypeId,Id)
)
create table ThingToken
(
ThingId int not null,
TokenId int not null,
TypeId int not null,
constraint pk_ThingToken
primary key (ThingId,TokenId),
constraint fk_ThingToken_Thing
foreign key (TypeId,ThingId) references Thing(TypeId, Id),
constraint fk_ThingToken_TypeToken
foreign key (TypeId,TokenId) references TypeToken(TypeId, TokenId)
)
我有 Thing
个 Type
。我还有这些 Token
与 Type
相关联。现在我想说一个Thing
有Token
的组合。可能的 table 表示是:
| Thing | | Type | | Token | | TypeToken | | ThingToken |
|-------| |------| |-------| |-----------| |------------|
| Id | | Id | | Id | | TypeId | | ThingId |
| Type | |------| |-------| | TokenId | | TokenId |
|-------| |-----------| |------------|
为了数据库的完整性,我想强制要求 Thing
只能有 Token
,前提是它们之前与 Type
相关联。我最好的选择是什么?
是的,你可以!这是您需要的示例,
CREATE TABLE Foo (
FooId INT
, Value VARCHAR(10)
)
CREATE TABLE Bar (
BarId INT
, FooId INT
, Value VARCHAR(10)
)
GO
CREATE FUNCTION CheckFooExistsOnBar
(
@FooId INT
)
RETURNS BIT
AS
BEGIN
DECLARE @Response BIT = 0;
IF EXISTS (SELECT * FROM Bar WHERE FooId = @FooId)
SET @Response = 1;
RETURN @Response
END
GO
ALTER TABLE Foo
ADD CONSTRAINT CHK_FooId_Foo
CHECK (dbo.CheckFooExistsOnBar(FooId) = 1)
INSERT INTO Foo (FooId, Value) VALUES (1, '')
查看more
一种方法是将 TypeId 添加到 ThingToken table,这样您就可以在外键中使用它。您还需要对 Thing 进行额外的唯一约束,但您可以将其放在 (TypeId,Id) 上,因此它对于按 TypeId 进行查找也很有用,并且在物理上与仅 (TypeId) 上的非聚集索引相同。
EG:
use tempdb
go
drop table if exists ThingToken
drop table if exists TypeToken
drop table if exists Token
drop table if exists Thing
drop table if exists Type
--| Thing | | Type | | Token | | TypeToken | | ThingToken |
--|-------| |------| |-------| |-----------| |------------|
--| Id | | Id | | Id | | TypeId | | ThingId |
--| Type | |------| |-------| | TokenId | | TokenId |
--|-------| |-----------| |------------|
create table Type(Id int primary key)
create table Token(Id int primary key)
create table TypeToken
(
TypeId int not null references Type,
TokenId int not null references Token,
constraint pk_TypeToken
primary key (TypeId,TokenId)
)
create table Thing
(
Id int not null primary key,
TypeId int references Type,
constraint ak_Thing
unique (TypeId,Id)
)
create table ThingToken
(
ThingId int not null,
TokenId int not null,
TypeId int not null,
constraint pk_ThingToken
primary key (ThingId,TokenId),
constraint fk_ThingToken_Thing
foreign key (TypeId,ThingId) references Thing(TypeId, Id),
constraint fk_ThingToken_TypeToken
foreign key (TypeId,TokenId) references TypeToken(TypeId, TokenId)
)