我在SQL server2005中有一个简单的表,包含3列:DateStart、DateEnd和Value.我try 设置"表判断约束",以避免插入重叠记录.例如,如果在这样的表中存在DateStart=2012-01-01(1月1日)和DateEnd 2012-01-15(1月15日)的记录,则判断约束必须避免插入DateStart=2012-01-10(无用DateEnd)的记录、DateEnd=2012-01-10(无用DateStart)的记录或DateStart 2011-12-10和DateEnd 2012-02-01的记录.

我是这样定义UDF的:

CREATE FUNCTION [dbo].[ufn_checkOverlappingDateRange]
(
    @DateStart AS DATETIME
    ,@DateEnd AS DATETIME
)
RETURNS BIT 
AS
BEGIN
  DECLARE @retval BIT
  /* date range at least one day */
  IF (DATEDIFF(day,@DateStart,@DateEnd) < 1)
    BEGIN
      SET @retval=0
    END
  ELSE
    BEGIN
      IF EXISTS
        (
          SELECT
              *
            FROM [dbo].[myTable]
            WHERE
            ((DateStart <= @DateStart) AND (DateEnd > @DateStart))
            OR
            ((@DateStart <= DateStart) AND (@DateEnd > DateStart))
        )
        BEGIN
          SET @retval=0
        END
    ELSE
      BEGIN
            SET @retval=1
          END
        END
  RETURN @retval
END

然后我想支票可能是这样的:

ALTER TABLE [dbo].[myTable]  WITH CHECK ADD  CONSTRAINT [CK_OverlappingDateRange] CHECK  ([dbo].[ufn_checkOverlappingDateRange]([DateStart],[DateEnd])<>(0))

但即使使用[myTable]empty EXISTS,当我插入第一条记录时,操作符也会返回true.我在哪里?可以这样设置约束吗?

顺便说一句,我认为DateStart包括在范围内,而DateEnd不包括在范围内.

推荐答案

正在执行判断after行已被插入,因此范围与其自身重叠.

你需要修改你的WHERE,比如:@MyTableId <> MyTableId.


顺便说一句,你的WHERE表达式可以简化.

如果:

  • 一个范围的结束在另一个范围的开始之前
  • or一个范围的开始在另一个范围的结束之后.

可以用SQL编写,比如:

WHERE @DateEnd < DateStart OR DateEnd < @DateStart

把它取反,得到do%重叠的范围……

WHERE NOT (@DateEnd < DateStart OR DateEnd < @DateStart)

……根据De Morgan's laws,等于……

WHERE NOT (@DateEnd < DateStart) AND NOT (DateEnd < @DateStart)

.这与以下内容相同:

WHERE @DateEnd >= DateStart AND DateEnd >= @DateStart

所以你的期末考试应该是:

WHERE
    @MyTableId <> MyTableId
    AND @DateEnd >= DateStart
    AND DateEnd >= @DateStart

[SQL Fiddle]

NOTE: to allow ranges to "touch", use 100 in the starting expression, which would produce 101 in the final expression.

Database相关问答推荐

在多组MongoDB中查找最新文档的有效方法

如何在华为Appcube中创建和使用对象(模型)?

更新数据库后如何更新redis?

多列索引的顺序

如何将 PHP 会话数据保存到数据库而不是文件系统中?

如何将 MySQL 5.5.40 升级到 MySQL 5.7

Symfony ArrayCollection 与 PersistentCollection

C# 连接到数据库并列出数据库

保存图像:文件还是 blob?

SQL Server 简单插入语句超时

如何将数据库从一台计算机复制到另一台计算机?

免费的便携式数据库有哪些?

行之间的 SQL 差异

我们如何保存在 sqlite3 中创建的数据库

如何在实体-属性-值设计中处理不同的数据类型(例如,具有多列的单个表或每种数据类型的多个表)?

省略日期中的毫秒数

Twisted + SQLAlchemy 和最好的方法

是否有任何支持协议缓冲区的数据库?

Windows phone 7 的本地 Sql 数据库支持

使用 oracle sql developer 从一个数据库复制到另一个数据库 - 连接失败