我有以下查询:
SELECT
T2.PseudoDateColumn
FROM
(
SELECT
*
FROM T1
WHERE
PseudoDateColumn <> -1
) T2
INNER JOIN T3
ON T2.T2_key = T3.T3_key
WHERE
CAST(CAST(T2.PseudoDateColumn AS VARCHAR) AS DATE)
BETWEEN
DATEADD(mm, -1, DATEADD(mm, DATEDIFF(mm, 0, GETDATE()), 0))
AND DATEADD(ms, -3, DATEADD(mm, 0, DATEADD(mm, DATEDIFF(mm, 0, GETDATE()), 0)))
PseudoDateColumn
是int
中的T1
。非实际日期的值具有-1
占位符。所有其他日期都是实际日期(仅存储为int
)。因此,在将-1
投射到PseudoDateColumn
之前,我需要首先过滤掉所有DATE
值,以便我可以使用BETWEEN
。当我在没有join
的情况下运行此脚本时,它可以正常工作。但是,当我使用join
运行它时,SQL会抛出错误:
“从字符转换日期和/或时间时转换失败 字符串“
我不知道为什么会这样。就像SQL在子查询之前进行CASTing一样。
更新: 我错误地写了SQL Server 2008.我实际上是在 PDW AU5 上运行它,它有SQL Server 2012.但我不认为这会产生影响。
此外,以下是PseudoDateColumn
中的一些示例数据。所有值均采用YYYYMMDD形式。
PseudoDateColumn
-----------------
20150112
20160305
20111009
答案 0 :(得分:0)
行为的最可能解释是存储在PseudoDateColumn
中的“坏”值。但是你应该可以调试它。
当SQL Server具有一个非常适合DATE
数据类型的自定义设计用于存储日期值时,将“日期”值存储在整数列中似乎是一种反模式。
但是,如果您需要使用已有的内容,并在不改变架构定义的情况下解决问题......
SQL Server有一个ISDATE
函数,您可以使用test test测试字符串的有效性。不幸的是,ISDATE
执行的检查并不像实际的CAST
那样严格,但它确实捕获了最令人震惊的“坏”值。
我的建议:
而不是将整数转换为日期(存储在列中的整数值...
将您的文字DATE值转换/转换为整数,转换为与列(整数)相同的数据类型/格式,并与原始整数列进行比较。
所以你的查询会是这样的:
WHERE T2.PseudoDateColumn >= CONVERT(INT, CONVERT(VARCHAR(8), datexpr1, 112) )
AND T2.PseudoDateColumn < CONVERT(INT, CONVERT(VARCHAR(8), datexpr2, 112) )
在该示例中, dateexpr1
和 dateexpr2
将替换为返回DATE
数据类型的表达式,如表达式在原始查询中。
注意:这种类型的范围比较取决于存储的整数值是规范的。 (以年份为先(四位数),然后是月份(两位数),然后是一天(两位数)。在该表示中,我们保证比较
(int)a <= (int)b < (int)c
将产生与
相同的结果 (date)a <= (date)b < (date)c
(除了因“无法”转换为有效日期的“坏”整数值而产生的差异...例如,具有无效“月”和/或“日”部分的整数值,例如{ {1}}(月份为13,日期为零)
一个整数比较检查2016年的伪数据将“正常”,而不会抛出错误......
20161300
这种方法完全避免了尝试将“坏”伪造的整数值转换为20160101 <= 20161300 < 2017000 -> TRUE
的问题。但始终可以将有效的DATE转换为DATE
格式的整数。
作为此模式的一个额外好处,使用裸YYYYMMDD
列上的谓词,SQL Server可能能够有效地使用以PseudoDateColumn
作为前导列的索引。
如果您在将PseudoDateColumn
转换为DATE时设置为死,则可以先使用PseudoDateColumn
函数执行验证值的条件测试。像这样:
ISDATE
答案 1 :(得分:0)
我知道这是一篇旧文章,但我认为这可以对某人有所帮助。尝试在内部联接中将VARCHAR
输入参数转换/广播到UNIQUEIDENTIFIER
时遇到类似的错误。我的所有数据都是有效的,并且如果在联接之外完成转换,则转换效果很好,但是在联接期间 会失败。实际上,我什至在SQL Server Management Studio的结果窗格中都得到了结果,但是仍然抛出该错误。对我有用的是使用TRY_CAST
或TRY_CONVERT
而不是CAST
或CONVERT
。我友善的邻里DBA建议使用此解决方案,因为它可以确保及早执行或类似的方法。