帮助超出范围的值

Doc*_*jay 2 sql-server-2008-r2 datetime2

我有这个查询给我一个错误

将 varchar 数据类型转换为 datetime 数据类型导致值超出范围。

询问:

select 
    COUNT(*) 
from 
    dbo.patient
INNER JOIN 
    dbo.study on dbo.patient.pk = dbo.study.patient_fk
              and dbo.study.study_datetime IS NOT NULL
              and dbo.patient.pat_birthdate IS NOT NULL
              and dbo.study.study_datetime <= DATEADD(D, -2192, GETDATE())
              and dbo.patient.pat_birthdate <= DATEADD(D, -7670, GETDATE());
Run Code Online (Sandbox Code Playgroud)

我读到这可能有助于转换为“DATETIME2”,但我无法弄清楚如何正确转换列“s.study_datetime”,因为该列很可能有一些错误的值作为条目。

Aar*_*and 5

您的 varchar 列中包含错误数据,您无法真正控制 SQL Server 何时尝试评估它们(在任何筛选发生之前或之后)。因此,您可以添加防止它们被包含在内的 where 子句(通过仅检查值是日期的行),但仍然无法保证 where 子句将被评估的顺序(这意味着您可能仍然会得到一个错误)。因此,除了这些过滤器(逻辑上可以替换您的 NOT NULL 过滤器)之外,您还可以确保仅在谓词实际上是有效日期时才对其进行评估。

SELECT COUNT(*) 
FROM dbo.patient AS p
INNER JOIN dbo.study AS s
  ON s.patient_fk = p.pk
WHERE ISDATE(p.pat_birthdate) = 1
AND ISDATE(s.study_datetime) = 1
AND CASE WHEN ISDATE(s.study_datetime) = 1 THEN s.study_datetime END 
  <= DATEADD(DAY, -2192, GETDATE())
AND CASE WHEN ISDATE(p.pat_birthdate) = 1 THEN p.pat_birthdate END 
  <= DATEADD(DAY, -7670, GETDATE());
Run Code Online (Sandbox Code Playgroud)

接下来,请修复表格,以便随机垃圾无法再进入这些列。首先使用以下方法识别不良数据:

SELECT * FROM dbo.study 
  WHERE ISDATE(study_datetime) = 0;

SELECT * FROM dbo.patient
  WHERE ISDATE(pat_birthdate) = 0;
Run Code Online (Sandbox Code Playgroud)

然后相应地更正(它们可能都是相同模式的“日期”,或者它真的可能是一堆随机垃圾,您只需将其设置为 NULL)。一旦那里没有错误值,您可以将数据类型更改为 DATE 或 DATETIME,因为它从一开始就应该如此。

请看以下帖子: