是否可以强制基于数据库完整性的间接关系

Is it possible to enforce database integrity based indirect relationship

我有 ThingType。我还有这些 TokenType 相关联。现在我想说一个ThingToken的组合。可能的 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)
)