列间唯一性约束

时间:2016-03-10 07:07:54

标签: sql sql-server

数据库结构:

表1(T1):

|I1|I2|I3|
|1 |1 |1 |
|2 |2 |2 |
    .
    .

约束上:

  • 群集主键:I1,I2,I3

表2(T2):

|AI1|AI2|AI3|BI1|BI2|BI3|
|1  |1  |1  |2  |2  |2  |
            .
            .

约束上:

  • AI1,AI2,AI3参考T1(I1,I2,I3)
  • BI1,BI2,BI3参考T1(I1,I2,I3)
  • AI1,AI2,AI3,BI1,BI2,BI3 Unique

我要添加的内容
对于当前提到的约束,仍然可以添加具有这样的

的另一行
|2|2|2|1|1|1|

这种可能性也应该被停止。换句话说,AI1,AI2,AI3不能再存在BI1,BI2,BI3

的组合

有没有办法实现这个目标?

我想在每次向T2添加新条目时使用触发器,然后删除新添加的行,但这不是一个优雅的解决方案。此外,添加行的代码将假定已添加行,但实际上它不会保留。

2 个答案:

答案 0 :(得分:1)

请参阅SQL CHECK约束。 我们可以在CHECK约束中使用UDF来验证列。 有关详细信息http://blog.codefluententities.com/2012/11/27/using-the-sql-server-template-producer-to-generate-clustered-indexes/

答案 1 :(得分:1)

您可以使用帮助程序表和indexed view

来执行此操作
create table dbo.Two (
    N int not null,
    constraint PK_Two PRIMARY KEY (N),
    constraint CK_Two_Two CHECK (N in (1,2))
)
go
insert into dbo.Two(N) values (1),(2)
go
create view dbo.DRI_T2_MoreUnique
with schemabinding
as
    select
        CASE WHEN N=1 THEN AI1 ELSE BI1 END as I1,
        CASE WHEN N=1 THEN AI2 ELSE BI2 END as I2,
        CASE WHEN N=1 THEN AI3 ELSE BI3 END as I3
    from
        dbo.T2
            inner join
        dbo.Two
            on
                1=1
go

如果您有一个数字表,您可以将其用作帮助程序,而不是创建特殊的Two表,只需确保您只在视图中从中选择两行。

基本上,帮助程序表用于帮助我们执行部分unpivot操作,但其方式与索引视图兼容。

完整的脚本:

create table dbo.T1 (
    I1 int not null,
    I2 int not null,
    I3 int not null,
    constraint PK_T1 PRIMARY KEY (I1,I2,I3)
)
go
insert into dbo.T1 (I1,I2,I3) values
(1,1,1),(2,2,2)
go
create table dbo.T2 (
    AI1 int not null,
    AI2 int not null,
    AI3 int not null,
    BI1 int not null,
    BI2 int not null,
    BI3 int not null,
    constraint PK_T2 PRIMARY KEY (AI1,AI2,AI3,BI1,BI2,BI3),
    constraint FK_T2_T1_A FOREIGN KEY (AI1,AI2,AI3)
        references T1 (I1,I2,I3),
    constraint FK_T2_T1_B FOREIGN KEY (BI1,BI2,BI3)
        references T1 (I1,I2,I3)
)
go
insert into dbo.T2 (AI1,AI2,AI3,BI1,BI2,BI3) values
(1,1,1,2,2,2)
go
create table dbo.Two (
    N int not null,
    constraint PK_Two PRIMARY KEY (N),
    constraint CK_Two_Two CHECK (N in (1,2))
)
go
insert into dbo.Two(N) values (1),(2)
go
create view dbo.DRI_T2_MoreUnique
with schemabinding
as
    select
        CASE WHEN N=1 THEN AI1 ELSE BI1 END as I1,
        CASE WHEN N=1 THEN AI2 ELSE BI2 END as I2,
        CASE WHEN N=1 THEN AI3 ELSE BI3 END as I3
    from
        dbo.T2
            inner join
        dbo.Two
            on
                1=1
go
create unique clustered index IX_DRI_T2
    on dbo.DRI_T2_MoreUnique (I1,I2,I3)
go
insert into dbo.T2 (AI1,AI2,AI3,BI1,BI2,BI3) values
(2,2,2,1,1,1)

最终插入会产生此错误:

  

Msg 2601,Level 14,State 1,Line 1

     

无法在具有唯一索引“IX_DRI_T2”的对象“dbo.DRI_T2_MoreUnique”中插入重复的键行。重复键值为(2,2,2)。

     

声明已经终止。