Sql 日期时间';转换失败';使用案例比较时出错
我有一个存储字段/值对以进行比较的表,例如:Sql 日期时间';转换失败';使用案例比较时出错,sql,sql-server,datetime,case,type-conversion,Sql,Sql Server,Datetime,Case,Type Conversion,我有一个存储字段/值对以进行比较的表,例如: 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
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 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')
所有内容都返回为datetime,这意味着即使int
值也被转换为日期,这让我相信这种类型的CASE
转换是不允许的。即使CASE
表示要将“Name”字段转换为varchar
,它还是将所有内容转换为datetime
如果这是标准的SQL Server行为,是否有任何解决方法可用于进行这些转换?我知道您试图执行的操作,但不能对这样的单个值使用多个类型。它们都需要是相同的数据类型,才能按照您正在尝试的方式执行
这应该满足您的需要,但这将导致性能不佳,因为没有索引可用于此类比较
Select *
From ComparisonTable
Where
(
FieldName = 'StartDate'
And Cast(ValueA As DateTime) = Cast(ValueB As DateTime)
)
Or
(
FieldName = 'Amount'
And Cast(ValueA As Int) = Cast(ValueB As Int)
)
Or
(
FieldName Not In ('StartDate', 'Amount')
And Cast(ValueA As Varchar (Max)) = Cast(ValueB As Varchar (Max))
)
另一个选项是在数据类型转换后将所有内容转换为VARCHAR
:
Select *
From ComparisonTable
Where
(
case
when FieldName = 'StartDate' then CAST(CAST(ValueA as datetime) As Varchar (Max))
when FieldName = 'Amount' then CAST(CAST(ValueA as int) AS Varchar (Max))
else CAST(ValueA as varchar(max))
end
)
=
(
case
when FieldName = 'StartDate' then CAST(CAST(ValueB as datetime) AS Varchar(Max))
when FieldName = 'Amount' then CAST(CAST(ValueB as int) As Varchar (Max))
else CAST(ValueB as varchar(max))
end
)
我提出的一个解决方案是使用UNION ALL
来分离不同的类型:
SELECT *
FROM ComparisonTable
WHERE FieldName = 'StartDate'
AND CAST(ValueA as datetime) = CAST(ValueB as datetime)
UNION ALL
SELECT *
FROM ComparisonTable
WHERE FieldName = 'Amount'
AND CAST(ValueA as int) = CAST(ValueB as int)
UNION ALL
SELECT *
FROM ComparisonTable
WHERE FieldName = 'Name'
AND CAST(ValueA as varchar(max)) = CAST(ValueB as varchar(max))
它是有效的,但我会将它与其他方法进行效率比较。嗯。。。将Amount
转换为Datetime
似乎有些奇怪。。。因为在你的例子中它的值是4。。。也许你是指整数还是数字?建议:仔细检查“Amount”的预期数据类型,不能在case表达式中混合这样的数据类型。它将遵循数据类型优先规则,并尝试将所有内容转换为日期时间。这是使用EAV的一个挑战部分,但它做得不太正确。在您的查询中,您必须将所有内容转换为字符数据类型才能使其正常工作。@xQbert这是一个复制/粘贴错误。它们正在转换为int