使用 CASE 比较时出现日期时间 'Conversion failed' 错误
Datetime 'Conversion failed' error when using CASE comparison
我有一个table存储Field/Value对进行比较,例如:
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 的值,寻找不匹配的值。由于它们在 table 中存储为 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)
我收到一个错误
Conversion failed when converting date and/or time from character
string
我认为这是因为在某处错误输入了 StartDate 值。但是,我进行了以下搜索:
Select *
From ComparisonTable
where FieldName = 'StartDate'
and
(ISDATE(ValueA) = 0
OR
ISDATE(ValueB) = 0)
对我来说,没有任何结果表明所有日期值都已正确存储。
我想知道是否还有其他人遇到过类似的问题,或者 SQL/SQL 服务器中是否有某些固有的东西不允许在 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
说要将 'Name' 字段转换为 varchar
,但它会将所有内容都转换为日期时间。
如果这是标准的 SQL 服务器行为,是否有任何解决方法可以用来进行这些转换?
我明白你想做什么,但你不能像那样对单个值使用多种类型。他们都需要是相同的数据类型才能按照您尝试的方式进行操作。
这应该可以满足您的要求,但这会导致性能不佳,因为没有索引可用于此类比较。
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))
它有效,但我会将其与其他方法进行比较以提高效率。
我有一个table存储Field/Value对进行比较,例如:
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 的值,寻找不匹配的值。由于它们在 table 中存储为 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)
我收到一个错误
Conversion failed when converting date and/or time from character string
我认为这是因为在某处错误输入了 StartDate 值。但是,我进行了以下搜索:
Select *
From ComparisonTable
where FieldName = 'StartDate'
and
(ISDATE(ValueA) = 0
OR
ISDATE(ValueB) = 0)
对我来说,没有任何结果表明所有日期值都已正确存储。
我想知道是否还有其他人遇到过类似的问题,或者 SQL/SQL 服务器中是否有某些固有的东西不允许在 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
说要将 'Name' 字段转换为 varchar
,但它会将所有内容都转换为日期时间。
如果这是标准的 SQL 服务器行为,是否有任何解决方法可以用来进行这些转换?
我明白你想做什么,但你不能像那样对单个值使用多种类型。他们都需要是相同的数据类型才能按照您尝试的方式进行操作。
这应该可以满足您的要求,但这会导致性能不佳,因为没有索引可用于此类比较。
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))
它有效,但我会将其与其他方法进行比较以提高效率。