当我尝试执行以下代码时,出现错误"向'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
Run Code Online (Sandbox Code Playgroud)
如您所见,DATEADD()的结果不能小于最小值.而且,不能调用DATEADD(),因为SELECT必须不返回任何内容.这是一个SQL服务器错误吗?
该SMALLDATETIME值有下列日期范围:
1900-01-01至2079-06-06
1900年1月1日至2079年6月6日
您收到错误是因为您的计算导致日期超出此范围:
DECLARE @BegDate SMALLDATETIME = '19000101'
SELECT @BegDate
SELECT DATEADD(DAY, -1, @BegDate)
Run Code Online (Sandbox Code Playgroud)
问题是为什么SELECT东西是之前执行FROM,JOIN以及WHERE东西,因为这是不是SELECT语句的逻辑处理顺序.
如果将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
Run Code Online (Sandbox Code Playgroud)
您可以使用它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)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2682 次 |
| 最近记录: |