我有一个临时区域,我正在尝试验证数据,经过多次验证迭代。目前,我正在使用nvarchar(50)列来解决一些问题,我试图将其转换为日期。
我知道字符串格式不正确导致日期转换失败的常见缺陷,所以这就是我正在做的事情。
SELECT *
FROM ( SELECT * FROM STAGE_TABLE WHERE ISDATE(DATE_COL) = 1)
WHERE CAST(DATE_COL AS DATE) < GETDATE()
...这导致标准“从字符串转换日期和/或时间时转换失败。”
但是这里的事情对我来说很奇怪。如果我将上述声明更改为以下内容:
SELECT CAST(DATE_COL AS DATE)
FROM ( SELECT * FROM STAGE_TABLE WHERE ISDATE(DATE_COL) = 1)
...一切都很好,我所做的就是将演员从where子句移动到select子句。我想我在基本层面上缺少一些东西。
FWIW,如果我在没有STAGE_TABLE
条款的情况下从WHERE ISDATE
提取所有记录,我的日期字符串就会很差。
任何见解都非常感谢!
答案 0 :(得分:3)
您应该发现第一个查询将两个WHERE子句合并为一个,并在ISDATE(失败)之前计算出CAST。
第二个查询显然必须首先处理WHERE,因此CAST永远不会看到错误的数据
我刚刚测试过并且可以验证:
create table STAGE_TABLE ( date_col nvarchar(50) )
insert into STAGE_TABLE select 'a'
insert into STAGE_TABLE select '20100101'
第一次查询
SELECT *
FROM ( SELECT * FROM STAGE_TABLE WHERE ISDATE(DATE_COL) = 1) X
WHERE CAST(DATE_COL AS DATE) < GETDATE()
第一个计划
|--Filter(WHERE:(isdate([tempdb].[dbo].[STAGE_TABLE].[date_col])=(1)))
|--Table Scan(OBJECT:([tempdb].[dbo].[STAGE_TABLE]), WHERE:(CONVERT(date,[tempdb].[dbo].[STAGE_TABLE].[date_col],0)<getdate()))
第二次查询
SELECT CAST(DATE_COL AS DATE)
FROM ( SELECT * FROM STAGE_TABLE WHERE ISDATE(DATE_COL) = 1) X
第二个计划
|--Compute Scalar(DEFINE:([Expr1004]=CONVERT(date,[tempdb].[dbo].[STAGE_TABLE].[date_col],0)))
|--Filter(WHERE:(isdate([tempdb].[dbo].[STAGE_TABLE].[date_col])=(1)))
|--Table Scan(OBJECT:([tempdb].[dbo].[STAGE_TABLE]))
似乎没有一个提示/选项来修复第一个查询(因为它被卷入一个WHERE子句),但你可以使用它来处理一个扫描过程中的两个条件。
SELECT *
FROM (SELECT * FROM STAGE_TABLE) X
WHERE CAST(CASE WHEN ISDATE(DATE_COL) = 1 THEN DATE_COL ELSE NULL END AS DATE) < GETDATE()