使用通配符值时的SQL唯一性约束

时间:2011-06-07 14:38:08

标签: sql-server constraints

考虑下表,该表指定在一周的特定日期禁止的水果。 DayOfWeek可以为空,其中NULL表示在所有天中禁止使用此类水果。

Fruit        DayOfWeek
----------------------
Kiwi         NULL
Apples       Monday
Strawberries Monday
Oranges      Tuesday
Bananas      Wednesday
Pineapple    Thursday

是否可以在此表上实施一个约束,阻止我插入值(Kiwi, Monday),因为新手已经在周一(以及每隔一天)被现有(Kiwi, NULL)行禁止。< / p>

最好不要使用触发器来实现

4 个答案:

答案 0 :(得分:3)

除非你有充分的理由,否则你不应该改变NULL的含义。 Null反映了一个未知的值,所以我会读到这个,因为我们不知道一周中哪一天被禁止。然后,您将更改逻辑以存储禁止Kiwi的每周的每一天的记录。

如果你需要写一个查询说明星期一给我所有的禁果,该怎么办?您需要将查询编写为

select * from BadFruit where DayOfWeek='Monday' || DayOfWeek is null

更有效且更容易理解的查询将消除or子句。

答案 1 :(得分:1)

我个人并不喜欢NULL意味着所有的想法,但是当NULL可能超出范围时,将其更改为每天包含一行。

如果触发器不是一个选项,我会查看一个CHECK CONSTRAINT并设置一个测试你试图避免的条件的函数。

答案 2 :(得分:1)

我同意其他人的意见,我可能会瞄准与您展示的模型不同的模型,但如果您在其上出售,那么以下似乎可以做您想要的:

create table dbo.Weekdays (
    DayOfWeek varchar(10) not null,
    constraint PK_Weekdays PRIMARY KEY (DayOfWeek)
)
go
create table dbo.Exclusions (
    Fruit varchar(20) not null,
    DayOfWeek varchar(10) null,
    /* PK? */
    constraint FK_Exclusions FOREIGN KEY (DayOfWeek) references Weekdays (DayOfWeek)
)

不确定Exclusions表中的PK应该是什么,并不是从你所展示的内容中看出来的,但是它应该是你的表。我们需要引入Weekdays表来使后面的视图工作*。现在填充它:

insert into dbo.Weekdays (DayOfWeek)
select 'Monday' union all
select 'Tuesday' union all
select 'Wednesday' union all
select 'Thursday' union all
select 'Friday' union all
select 'Saturday' union all
select 'Sunday'

您的样本数据:

insert into dbo.Exclusions (Fruit,DayOfWeek)
select 'Kiwi',NULL union all
select 'Apples','Monday' union all
select 'Strawberries','Monday' union all
select 'Oranges','Tuesday' union all
select 'Bananas','Wednesday' union all
select 'Pineapple','Thursday'

现在我们创建视图来实现约束:

create view dbo.Exclusions_NullExpanded
with schemabinding
as
    select
        e.Fruit,
        wd.DayOfWeek
    from
        dbo.Exclusions e
            inner join
        dbo.Weekdays wd
            on
                e.DayOfWeek = wd.DayOfWeek or
                e.DayOfWeek is null
go
create unique clustered index IX_Exclusions_NoDups on dbo.Exclusions_NullExpanded (Fruit,DayOfWeek)

并且,如果我们尝试插入您不希望我们的行:

insert into dbo.Exclusions (Fruit,DayOfWeek)
select 'Kiwi','Monday'

我们得到:

Msg 2601, Level 14, State 1, Line 1
Cannot insert duplicate key row in object 'dbo.Exclusions_NullExpanded' with unique index 'IX_Exclusions_NoDups'.
The statement has been terminated.

*我最初尝试在不引入Weekdays表的情况下执行此操作,并使其在视图定义中显示为内联,作为文字行的子选择。但是你不能创建在这样的视图上强制执行我们想要的约束的索引。

答案 3 :(得分:-1)

试试此链接http://www.java2s.com/Code/SQL/Select-Clause/SettingaUniqueConstraint.htm

对于MySQL,您可以设置唯一约束。