防止具有相同col1和不同col2的行

时间:2014-02-03 16:48:42

标签: sql-server tsql sql-server-2005 constraints

是否可以创建一个约束来阻止同一Col2上的不同 Col1,其中第一列不能是NULL而不是第二列?< / p>

为了澄清我的要求,请考虑使用单行的示例数据:

MaterialNumber(varchar50, not null)    fiModel(int, null, fk)
1234-4321                              1

是否可以阻止具有相同MaterialNumber但不同fiModel的第二行?

Here's一个sql-fiddle,第二个INSERT应该失败,因为它是一个具有相同数字的不同模型。

如果链接腐烂:

(简化)表:

CREATE TABLE [dbo].[tabSparePartMasterData](
    [MaterialNumber] [varchar](50) NOT NULL,
    [fiModel] [int] NULL)

两行,第二次插入不可能:

INSERT INTO tabSparePartMasterData(MaterialNumber,fiModel)
VALUES('1234-4321', 1);
INSERT INTO tabSparePartMasterData(MaterialNumber,fiModel)
VALUES('1234-4321', 2);

请注意,fiModel可以是null,但如果它不为空,则无法添加相同或不同 fiModel的其他行。我已经使用计算列解决了MaterialNumber + fiModel(非空)上的唯一索引。但我坚持如何阻止不同的fiModel

2 个答案:

答案 0 :(得分:3)

您可以向表中添加持久列以支持此条件约束。如果您不想更改此表,则可以使用投影ChkMaterialNumber列并对其执行唯一约束的视图实现相同的策略。

CREATE TABLE [dbo].[tabSparePartMasterData]
(
    [YourPK] int identity(1,1) not null primary key,
    [MaterialNumber] [varchar](50) NOT NULL,
    [fiModel] [int] NULL
);
go

--add a computed column here to enforce the conditional constraint:
alter table [dbo].[tabSparePartMasterData] add [ChkMaterialNumber] as ( case when fiModel is null then cast(YourPK as varchar) else MaterialNumber end)

--now add unique constraint to the computed column:
create unique index ux_SparePartMasterData on [dbo].[tabSparePartMasterData]([ChkMaterialNumber]);
go



-- OK
INSERT INTO tabSparePartMasterData(MaterialNumber,fiModel)
VALUES('1234-4321', 1);

-- FAILS
INSERT INTO tabSparePartMasterData(MaterialNumber,fiModel)
VALUES('1234-4321', 2);

--OK
INSERT INTO tabSparePartMasterData(MaterialNumber,fiModel)
VALUES('1234-4321', null);

答案 1 :(得分:0)

在解决问题之后编辑我的答案。

我认为最好的解决方案,而不是使用触发器或函数是创建一个类型为UNIQUEIDENTIFIER的新列(我将其命名为fiModel1),应始终使用NEWID()填充。

然后创建一个计算列,如:

ALTER TABLE [dbo].[tabSparePartMasterData]
    ADD UNIQUECONST as cast([MaterialNumber] as varchar(150)) + case when fiModel is null then    cast(fiModel1 as varchar(150)) else '' end PERSISTED

之后,为此列创建一个约束,如:

ALTER TABLE [dbo].[tabSparePartMasterData]
ADD CONSTRAINT AK_MaterialNumber UNIQUE (UNIQUECONST);

最后,您可以添加前3个记录,但不能添加最后一个记录:

INSERT INTO tabSparePartMasterData(MaterialNumber,fiModel, fiModel1) VALUES('1234-4321', null, NEWID());
INSERT INTO tabSparePartMasterData(MaterialNumber,fiModel, fiModel1) VALUES('1234-4321', null, NEWID());
INSERT INTO tabSparePartMasterData(MaterialNumber,fiModel, fiModel1) VALUES('1234-4321', 1, NEWID());
INSERT INTO tabSparePartMasterData(MaterialNumber,fiModel, fiModel1) VALUES('1234-4321', 2, NEWID());

我认为这可以解决你的问题