【发布时间】:2016-02-17 19:02:36
【问题描述】:
我有一个存储字段/值对的表格以供比较,例如:
ID FieldName ValueA ValueB
---- ---------- ------- ------
1 Name ABC XYZ
1 StartDate 2015-05-04 2015-06-05
1 Amount 4 4
2 Name DEF UVW
2 StartDate 2015-03-22 2015-02-11
2 Amount 4 4
我正在尝试比较 ValueA 和 ValueB 的值,寻找不匹配的值。由于它们在表中存储为 varchar(max),因此有时会在不应该出现的地方出现不匹配,即
ID FieldName ValueA ValueB
---- ---------- ------- ------
3 StartDate 2015-01-30 01/30/2015
所以我使用CASE 语句在比较之前转换数据类型,即
Select *
From ComparisonTable
where
(case when FieldName = 'StartDate' then CAST(ValueA as datetime)
when FieldName = 'Amount' then CAST(ValueA as int)
else CAST(ValueA as varchar(max))
end)
=
(case when FieldName = 'StartDate' then CAST(ValueB as datetime)
when FieldName = 'Amount' then CAST(ValueB as int)
else CAST(ValueB as varchar(max))
end)
我收到一个错误
从字符转换日期和/或时间时转换失败 字符串
我认为这是因为某处输入了错误的 StartDate 值。但是,我进行了以下搜索:
Select *
From ComparisonTable
where FieldName = 'StartDate'
and
(ISDATE(ValueA) = 0
OR
ISDATE(ValueB) = 0)
对我来说,没有任何结果表明所有日期值都已正确存储。
我想知道是否有其他人遇到过类似的问题,或者 SQL/SQL Server 中是否存在不允许在 WHERE/CASE 语句中进行这些类型的数据类型转换的东西?
更新
我尝试在一个简单的SELECT 中使用相同的CASE:
SELECT
(case when FieldName = 'StartDate' then CAST(ValueA as datetime)
when FieldName = 'Amount' then CAST(ValueA as int)
else CAST(ValueA as varchar(max))
end)
=
(case when FieldName = 'StartDate' then CAST(ValueB as datetime)
when FieldName = 'Amount' then CAST(ValueB as int)
else CAST(ValueB as varchar(max))
end)
WHERE FieldName IN ('StartDate','Amount')
一切都以日期时间的形式返回,这意味着即使 int 值也被转换为日期,这让我相信这种类型的 CASE 转换是不允许的。尽管CASE 说要将“名称”字段转换为varchar,但它会将所有内容都转换为日期时间。
如果这是标准 SQL Server 行为,是否有任何解决方法可用于进行这些转换?
【问题讨论】:
-
嗯...将
Amount转换为Datetime似乎很奇怪...因为在您的示例中它的值是4...也许您的意思是整数或数字?建议:仔细检查“金额”的预期数据类型 -
您不能在 case 表达式中混合这样的数据类型。它将遵循数据类型优先规则并尝试将所有内容转换为日期时间。这是使用 EAV 的具有挑战性的部分之一,并且做得不好。在您的查询中,您必须将所有内容转换为字符数据类型才能使其正常工作。
-
@xQbert 这是一个复制/粘贴错字。他们正在转换为
int
标签: sql sql-server datetime case type-conversion