Ant*_*llo 21 database sql-server database-design sql-server-2005 check-constraints
我在sql server 2005中有一个简单的表,有3列:DateStart,DateEnd和Value.我试图设置"表检查约束"以避免插入重叠记录.例如,如果在此表中有DateStart = 2012-01-01(第一月1月)和DateEnd 2012-01-15(1月15日)的记录,则Check约束必须避免插入DateStart = 2012-01-10的记录(没有关心DateEnd),DateEnd = 2012-01-10(无关日期启动)的记录或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
Run Code Online (Sandbox Code Playgroud)
然后考虑检查可能是这样的:
ALTER TABLE [dbo].[myTable] WITH CHECK ADD CONSTRAINT [CK_OverlappingDateRange] CHECK ([dbo].[ufn_checkOverlappingDateRange]([DateStart],[DateEnd])<>(0))
Run Code Online (Sandbox Code Playgroud)
但即使使用[myTable]为空,EXISTS运算符在插入第一条记录时返回true.我在哪里wrog?是否可以设置这样的约束?
顺便说一下,我认为DateStart包含在范围内,DateEnd从范围中排除.
Bra*_*vic 29
插入行后正在执行CHECK ,因此范围与自身重叠.
您需要修改您的WHERE以包含以下内容:@MyTableId <> MyTableId
.
顺便说一句,您的WHERE表达式可以简化.
在下列情况下,范围不重叠:
哪个可以用SQL编写:
WHERE @DateEnd < DateStart OR DateEnd < @DateStart
Run Code Online (Sandbox Code Playgroud)
否定,为了得到该范围不重叠...
WHERE NOT (@DateEnd < DateStart OR DateEnd < @DateStart)
Run Code Online (Sandbox Code Playgroud)
...根据De Morgan的法律,它与...相同
WHERE (NOT (@DateEnd < DateStart) AND NOT (DateEnd < @DateStart))
Run Code Online (Sandbox Code Playgroud)
......这与:
WHERE @DateEnd >= DateStart AND DateEnd >= @DateStart
Run Code Online (Sandbox Code Playgroud)
所以你最后的WHERE应该是:
WHERE
@MyTableId <> MyTableId
AND @DateEnd >= DateStart
AND DateEnd >= @DateStart
Run Code Online (Sandbox Code Playgroud)
注意:要允许范围"触摸",请<=
在起始表达式中使用,这将在最终表达式中生成">".
归档时间: |
|
查看次数: |
13525 次 |
最近记录: |