当我尝试执行以下代码时,我收到错误"将值添加到' smalldatetime'列导致溢出":
DECLARE @t TABLE (ID UNIQUEIDENTIFIER, BegDate SMALLDATETIME, EndDate SMALLDATETIME)
INSERT INTO @t
SELECT NEWID(), '19000101', '20151124'
-- This is to show you that nothing is really selected
SELECT 'You will never see it'
FROM @t r1
INNER JOIN @t r2 ON r2.ID = r1.ID
WHERE 1=1
AND r1.BegDate > r2.BegDate
AND r1.EndDate <= r2.EndDate
SELECT r1.ID, r2.BegDate, DATEADD(DAY, -1, r1.BegDate) AS EndDate
FROM @t r1
INNER JOIN @t r2 ON r2.ID = r1.ID
WHERE 1=1
AND r1.BegDate > r2.BegDate -- This guarantees that r1.BegDate is not minimal value
AND r1.EndDate <= r2.EndDate
如您所见,DATEADD()的结果不能小于最小值。而且,不能调用DATEADD(),因为SELECT必须不返回任何内容。 它是SQL服务器的错误吗?
答案 0 :(得分:5)
smalldatetime值具有以下日期范围:
1900-01-01至2079-06-06
1900年1月1日至2079年6月6日
您收到错误是因为您的计算导致日期超出此界限:
DECLARE @BegDate SMALLDATETIME = '19000101'
SELECT @BegDate
SELECT DATEADD(DAY, -1, @BegDate)
问题是SELECT
内容在FROM
,JOIN
和WHERE
之前执行的原因,因为这不是Logical Processing Order of the SELECT statement。
如果将19000101
值更改为19000102
,只是为了获得SQL引擎正在构建的执行计划,您应该看到:
Compute Scalar
实际上是DATEADD
函数执行:
因此,执行DATEADD
函数并抛出错误。这是因为:
请注意,确定语句的实际物理执行 由查询处理器和订单可能会有所不同。
SELECT r1.ID, r2.BegDate, IIF(r1.BegDate = '19000101', NULL, DATEADD(DAY, -1, r1.BegDate)) AS EndDate
FROM @t r1
INNER JOIN @t r2 ON r2.ID = r1.ID
WHERE 1=1
AND r1.BegDate > r2.BegDate -- This guarantees that r1.BegDate is not minimal value
AND r1.EndDate <= r2.EndDate
您可以使用OPTION(FORCE ORDER)
更改执行计划并使查询正常工作:
SELECT r1.ID, r2.BegDate, DATEADD(DAY, -1, r1.BegDate) AS EndDate
FROM @t r1
INNER JOIN @t r2 ON r2.ID = r1.ID
WHERE 1=1
AND r1.BegDate > r2.BegDate -- This guarantees that r1.BegDate is not minimal value
AND r1.EndDate <= r2.EndDate
OPTION (FORCE ORDER)
答案 1 :(得分:1)
我在这里收到了答案:
在这种情况下,我可以使用OPTION(FORCE ORDER):
SELECT r1.ID, r2.BegDate, DATEADD(DAY, -1, r1.BegDate) AS EndDate
FROM @t r1
INNER JOIN @t r2 ON r2.ID = r1.ID
WHERE 1=1
AND r1.BegDate > r2.BegDate -- This guarantees that r1.BegDate is not minimal value
AND r1.EndDate <= r2.EndDate
OPTION(FORCE ORDER)