[英]Strange issue when converting VarChar(max) to DATE or DATETIME in SQL Server 2008
SELECT Files.URL, Files.MD5, Files.Thumbnail, Files.Title, CONVERT(DATE, AttributeData.Keyword) AS DateUpdated, Attributes.Name AS DateType,
Metadata.metadata
FROM Files INNER JOIN
Metadata ON Files.ID = Metadata.FileID INNER JOIN
FilesToAttributeData ON Files.ID = FilesToAttributeData.FileID INNER JOIN
AttributeData ON FilesToAttributeData.AttributeDataID = AttributeData.ID INNER JOIN
Attributes ON AttributeData.AttributeID = Attributes.ID
WHERE (Files.GeneralSearch = 1) AND
(Attributes.Name = 'Process Date' OR Attributes.Name = 'Publish Date') AND
(ISDATE(AttributeData.Keyword) = 1) AND
(CONVERT(DATE, AttributeData.Keyword) > DATEADD(DAY, - 90, GETDATE()))
ORDER BY DateUpdated DESC
这是我原来的SQL查询。 它似乎可以在我们的开发环境中使用我们的数据。 但在生产中我收到以下错误。 “从字符串转换日期和/或时间时,消息241,级别16,状态1,行1转换失败。” 现在,如果我删除SELECT中的转换函数并输出AttributeData.Keyword,它将正常工作。 如果我单独留下并删除where子句中的convert函数,它将正常工作。 如果它们都存在,它将无法工作。
有什么想法会导致这种情况吗? 我试过CAST,我尝试过使用特定的日期样式。 我们的日期通常看起来像yyyymmdd。 一个例子是'20110318'。 如果我用此字符串替换AttributeData.Keyword,它也将失败。 我真的不知道这里发生了什么。
以下是有效查询的示例。
SELECT (AttributeData.Keyword) AS DateUpdated, Attributes.Name AS DateType
FROM Files INNER JOIN
Metadata ON Files.ID = Metadata.FileID INNER JOIN
FilesToAttributeData ON Files.ID = FilesToAttributeData.FileID INNER JOIN
AttributeData ON FilesToAttributeData.AttributeDataID = AttributeData.ID INNER JOIN
Attributes ON AttributeData.AttributeID = Attributes.ID
WHERE (Files.GeneralSearch = 1) AND
(Attributes.Name = 'Process Date' OR Attributes.Name = 'Publish Date') AND
(ISDATE(AttributeData.Keyword) = 1) AND
(CONVERT(DATE, AttributeData.Keyword) > DATEADD(DAY, - 90, GETDATE()))
ORDER BY DateUpdated DESC
DateUpdated DateType
20110318 Process Date
20110318 Process Date
20110315 Process Date
20110315 Process Date
20110303 Process Date
20110303 Publish Date
20110302 Process Date
20110301 Process Date
20110301 Publish Date
20110225 Process Date
20110223 Process Date
20110201 Publish Date
20110201 Process Date
20110127 Process Date
20110118 Publish Date
20110101 Publish Date
20110101 Publish Date
20101231 Process Date
20101231 Publish Date
在SQL Server中,除了CASE
语句之外,没有保证特定的评估顺序,因此它可能在ISDATE(AttributeData.Keyword) = 1
过滤器之前执行CONVERT(DATE, AttributeData.Keyword)
(您可以通过查看执行来确认这一点)计划)。
要解决此问题,您可以使用替换CONVERT(DATE, AttributeData.Keyword)
CASE
WHEN ISDATE(AttributeData.Keyword) = 1 THEN
CONVERT(DATE, AttributeData.Keyword)
END
所以你可以尝试一下
SELECT Files.URL,
Files.MD5,
Files.Thumbnail,
Files.Title,
CASE
WHEN ISDATE(AttributeData.Keyword) = 1 THEN
CONVERT(DATE, AttributeData.Keyword)
END AS DateUpdated,
Attributes.Name AS DateType,
Metadata.metadata
FROM Files
INNER JOIN Metadata
ON Files.ID = Metadata.FileID
INNER JOIN FilesToAttributeData
ON Files.ID = FilesToAttributeData.FileID
INNER JOIN AttributeData
ON FilesToAttributeData.AttributeDataID = AttributeData.ID
INNER JOIN Attributes
ON AttributeData.AttributeID = Attributes.ID
WHERE ( Files.GeneralSearch = 1 )
AND ( Attributes.Name = 'Process Date'
OR Attributes.Name = 'Publish Date' )
AND ( CASE
WHEN ISDATE(AttributeData.Keyword) = 1 THEN
CONVERT(DATE, AttributeData.Keyword)
END > DATEADD(DAY, -90, GETDATE()) )
ORDER BY DateUpdated DESC
你也可以尝试添加
(ISDATE(AttributeData.Keyword) = 1)
作为AttributeData的连接条件,但我认为你仍然不能保证执行顺序。
而这似乎工作正常....
DECLARE @tempFiles TABLE(DateUpdated varchar(MAX))
INSERT INTO @tempFiles(DateUpdated)
SELECT AttributeData.Keyword AS DateUpdated
FROM Files INNER JOIN
Metadata ON Files.ID = Metadata.FileID INNER JOIN
FilesToAttributeData ON Files.ID = FilesToAttributeData.FileID INNER JOIN
AttributeData ON FilesToAttributeData.AttributeDataID = AttributeData.ID INNER JOIN
Attributes ON AttributeData.AttributeID = Attributes.ID
WHERE (Files.GeneralSearch = 1) AND
(Attributes.Name = 'Process Date' OR Attributes.Name = 'Publish Date') AND
(ISDATE(AttributeData.Keyword) = 1) AND
(CONVERT(DATETIME, AttributeData.Keyword, 112) > DATEADD(DAY, - 90, GETDATE()))
ORDER BY DateUpdated DESC
SELECT CONVERT(DATE, DateUpdated) FROM @tempFiles
似乎Martin是正确的,因为SQL优化器正在重新排序哪些部分首先被评估,这意味着转换在ISDATE之前发生,所以我实际上正在处理无效日期。 ATM我知道解决这个问题的唯一方法就是使用临时表并在select语句中进行无需转换的评估,直到我准备好返回结果...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.