SQL约束:特定键每天只有一条记录

时间:2012-02-23 21:37:59

标签: sql sql-server sql-server-2005

有一种方法可以创建约束或某些内容,我只能为FK列的一天创建一条记录吗?即。

PK(IDENTITY(1,1))  FK_FIELD DATETIME
------------------------------
1                  1        2012-02-22 4:50 p.m.
2                  2        2012-02-23 12:00 p.m.
3                  2        2012-02-23 9:00 p.m.  -- This one should not be allowed because the FK_Field 2 would have 2 record in one day.
4                  1        2012-02-23 08:00 a.m 

希望有人明白我想要的是什么。

提前致谢。

4 个答案:

答案 0 :(得分:4)

考虑使用:

  • 1个或多个持久计算列
  • 对持久计算列的唯一约束

各种持久列的一些例子(非常感谢Aaron Bertrand):

  • Y YEAR(SOMEDATE)PERSISTED
  • M AS MONTH(SOMEDATE)PERSISTED
  • D AS MONTH(SOMEDATE)PERSISTED
  • YMD AS YEAR(SOMEDATE)* 10000 + MONTH(SOMEDATE)* 100 + DAY(SOMEDATE)PERSISTED
  • SOMEDATEDIFF DATEDIFF(DAY,0,SOMEDATE)PERSISTED
  • SOMEDATESMALL作为DATEADD(DAY,0,DATEDIFF(DAY,0,SOMEDATE))PERSISTED
  • SOMEDATESMALL AS CONVERT(DATETIME,FLOOR(CONVERT(FLOAT,SOMEDATE,105)),105)PERSISTED
  • SOMEDATESMALL AS CONVERT(DATE,SOMEDATE)PERSISTED - 需要SQL Server 2008

N.B。仔细选择这些例子以确保功能决定论。

这是一个示例SQL:

CREATE TABLE DATA
(
     ID INT NOT NULL IDENTITY,
     FK_FIELD INT NOT NULL,
     SOMEDATE DATETIME NOT NULL,
     SOMEDATESMALL AS DATEADD(DAY, 0, DATEDIFF(DAY, 0, SOMEDATE)) PERSISTED,
     CONSTRAINT PK_DATA PRIMARY KEY (ID),
     CONSTRAINT UQ_DATA_SOMEDATESMALL UNIQUE (FK_FIELD, SOMEDATESMALL)
);

如果你尝试了INSERT,那就是你得到的:

INSERT INTO DATA (FK_FIELD, SOMEDATE) VALUES (1, '2012-02-22 4:50PM'); -- SUCCESS
INSERT INTO DATA (FK_FIELD, SOMEDATE) VALUES (2, '2012-02-23 12:00PM'); -- SUCCESS
INSERT INTO DATA (FK_FIELD, SOMEDATE) VALUES (2, '2012-02-23 9:00PM'); -- CAUGHT
INSERT INTO DATA (FK_FIELD, SOMEDATE) VALUES (1, '2012-02-23 8:00AM'); -- SUCCESS

SQL Server Management Studio中显示的消息是:

  

Ms 2627,Level 14,State 1,Line 3
  违反UNIQUE KEY约束'UQ_DATA_SOMEDATESMALL'   无法在对象'dbo.DATA'中插入重复键   声明已经终止。

答案 1 :(得分:1)

您可以创建一个检查约束,该约束使用用户定义的函数来检查整个表是否存在今日条目。

CREATE TABLE #demo (
    some_date_field DATETIME NULL 
        CHECK (dbo.check_only_one(GETDATE())
)

答案 2 :(得分:1)

这是一种方法

create table t1 (pk int identity(1,1),fk_field int,theDate DateTime,
                 theDay as convert(varchar(12),theDate,102))
create unique index noDupes on t1 (fk_field,theDay)

您也可以使用约束,如Aaron所建议的那样

create table t1 (pk int identity(1,1),fk_field int,theDate DateTime,
                     theDay as convert(varchar(12),theDate,102)
    CONSTRAINT [noDupes] UNIQUE  ( [fk_field], [theDay])        )               
  • 添加一个仅包含日期日期部分的计算列。
  • 然后在密钥和计算字段

    上创建唯一索引
    insert into  t1 values (1,getDate())        
    insert into  t1 values (2,getDate())          
    insert into  t1 values (2,getDate())    -- ERROR    
    insert into  t1 values (3,getDate())
    

答案 3 :(得分:0)

我会尝试将日期与数据库的2个不同字段或组合中的日期分开。然后我会在日期添加一个唯一的约束。只要日期在您添加约束的列中,以下内容将阻止对同一日期进行任何输入。

ALTER TABLE XYZ
    ADD CONSTRAINT UNIQUE( the date field name)

还有一个非常有趣的主题,你应该检查一下在这里解决的类似问题How to create a unique constraint just on the date part of a datetime?

希望这有帮助