T-SQL错误:向'smalldatetime'列添加值会导致溢出.SQL服务器错误?

Fam*_* T. 3 t-sql sql-server

当我尝试执行以下代码时,出现错误"向'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服务器错误吗?

got*_*tqn 6

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)

在此输入图像描述

  • @PanagiotisKanavos - 有一个逻辑处理顺序,SQL数据库产品*应该跟随,或者,如果他们选择不遵循,应该产生相同的行为,就像他们遵循逻辑处理顺序一样.问题是,SQL Server有时会违反这个"好像"的要求. (3认同)