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”,因为该列很可能有一些错误的值作为条目。
您的 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,因为它从一开始就应该如此。
请看以下帖子: