Sql server CTE中的“转换失败”错误

Sql server CTE中的“转换失败”错误,sql-server,sql-server-2008,sql-server-2012,common-table-expression,Sql Server,Sql Server 2008,Sql Server 2012,Common Table Expression,下面是我用来获取年龄在25到34岁之间的所有用户的SQL Server 2012查询的精简版本。在我的桌子上 列反馈的类型为VarChar,并将用户的出生日期存储为VarChar,格式为dd-mm-yyyy。 列FeedbackDate类型为DateTime,基本上是用户以反馈的形式告诉我他的DOB的日期,我将其存储在反馈列中。 另外,当我尝试执行内部查询时,它成功地执行了,这表明在执行此内部查询之前,日期的格式不是问题 例如,当我执行以下查询时: SELECT CASE WHEN DA

下面是我用来获取年龄在25到34岁之间的所有用户的SQL Server 2012查询的精简版本。在我的桌子上

列反馈的类型为VarChar,并将用户的出生日期存储为VarChar,格式为dd-mm-yyyy。 列FeedbackDate类型为DateTime,基本上是用户以反馈的形式告诉我他的DOB的日期,我将其存储在反馈列中。 另外,当我尝试执行内部查询时,它成功地执行了,这表明在执行此内部查询之前,日期的格式不是问题

例如,当我执行以下查询时:

SELECT
CASE
    WHEN DATEADD(yy, DATEDIFF(yy, CONVERT(DATETIME, Feedback), FeedbackDate), CONVERT(DATETIME, Feedback)) < FeedbackDate
    THEN DATEDIFF(yy, CONVERT(DATETIME, Feedback), FeedbackDate)
    ELSE DATEDIFF(yy, CONVERT(DATETIME, Feedback), FeedbackDate) - 1
    END AS Age
FROM FeedbackTable
WITH AgeCTE AS
(
    SELECT
        CASE
            WHEN DATEADD(yy, DATEDIFF(yy, CONVERT(DATETIME, Feedback), FeedbackDate), CONVERT(DATETIME, Feedback)) < FeedbackDate
            THEN DATEDIFF(yy, CONVERT(DATETIME, Feedback), FeedbackDate)
        ELSE DATEDIFF(yy, CONVERT(DATETIME, Feedback), FeedbackDate) - 1
    END AS Age
    FROM FeedbackTable
)
SELECT COUNT(*) AS [25To34] FROM AgeCTE
我得到的输出是:

年龄

二十三 33 35 8. 等等

如果省略最后一个WHERE子句,即使整个CTE查询也可以工作。具体来说,如果我删除该节

WHERE (Age >= 25) AND (Age <= 34)
并执行以下查询:

SELECT
CASE
    WHEN DATEADD(yy, DATEDIFF(yy, CONVERT(DATETIME, Feedback), FeedbackDate), CONVERT(DATETIME, Feedback)) < FeedbackDate
    THEN DATEDIFF(yy, CONVERT(DATETIME, Feedback), FeedbackDate)
    ELSE DATEDIFF(yy, CONVERT(DATETIME, Feedback), FeedbackDate) - 1
    END AS Age
FROM FeedbackTable
WITH AgeCTE AS
(
    SELECT
        CASE
            WHEN DATEADD(yy, DATEDIFF(yy, CONVERT(DATETIME, Feedback), FeedbackDate), CONVERT(DATETIME, Feedback)) < FeedbackDate
            THEN DATEDIFF(yy, CONVERT(DATETIME, Feedback), FeedbackDate)
        ELSE DATEDIFF(yy, CONVERT(DATETIME, Feedback), FeedbackDate) - 1
    END AS Age
    FROM FeedbackTable
)
SELECT COUNT(*) AS [25To34] FROM AgeCTE
我得到以下输出:

25至34

九,


我不明白WHERE条款有什么问题。我在网上的某个地方读到它可能是短路,但我不知道怎么回事。任何帮助都将不胜感激。

首先:以字符串格式存储日期总是一个坏主意

其次:您的格式dd-mm-yyyy是-更糟糕的-特定于区域性的。使用不带第三个参数的CONVERT是赌博。这是否有效取决于您的系统设置

第一次尝试时,我会添加适当的代码:

如果仍然存在问题,可以使用此SQL Server 2012+

SELECT * 
FROM YourTable 
WHERE TRY_CONVERT(DATETIME,Feedback) IS NULL 

TRY\u CONVERT是一个非常新的函数,如果转换失败,它将返回NULL。

首先:以字符串格式存储日期总是一个坏主意

其次:您的格式dd-mm-yyyy是-更糟糕的-特定于区域性的。使用不带第三个参数的CONVERT是赌博。这是否有效取决于您的系统设置

第一次尝试时,我会添加适当的代码:

如果仍然存在问题,可以使用此SQL Server 2012+

SELECT * 
FROM YourTable 
WHERE TRY_CONVERT(DATETIME,Feedback) IS NULL 
TRY\u CONVERT是一个非常好的新函数,如果转换失败,它将返回NULL。

我相信您可以使用ISDATE检查值是否可以转换。如果不是,则可以返回零,该行将从查询中排除

WITH AgeCTE AS
(
  SELECT
    CASE
        WHEN DATEADD(yy, DATEDIFF(yy, CONVERT(DATETIME, Feedback), FeedbackDate), CONVERT(DATETIME, Feedback)) < FeedbackDate
        THEN DATEDIFF(yy, CONVERT(DATETIME, Feedback), FeedbackDate)
    ELSE 
      CASE 
        WHEN ISDATE(Feedback) = 1 
        THEN DATEDIFF(yy, CONVERT(DATETIME, Feedback), FeedbackDate) - 1
      ELSE
        0
      END
    END AS Age
  FROM FeedbackTable
)
SELECT COUNT(*) AS [25To34] 
FROM AgeCTE 
WHERE (Age >= 25) AND (Age <= 34)
不过,我将重复@Shnugo所说的,您应该在CONVERT语句中使用隐式格式参数,而不是使用VARCHAR存储日期。

我相信您可以使用ISDATE检查值是否可以转换。如果不是,则可以返回零,该行将从查询中排除

WITH AgeCTE AS
(
  SELECT
    CASE
        WHEN DATEADD(yy, DATEDIFF(yy, CONVERT(DATETIME, Feedback), FeedbackDate), CONVERT(DATETIME, Feedback)) < FeedbackDate
        THEN DATEDIFF(yy, CONVERT(DATETIME, Feedback), FeedbackDate)
    ELSE 
      CASE 
        WHEN ISDATE(Feedback) = 1 
        THEN DATEDIFF(yy, CONVERT(DATETIME, Feedback), FeedbackDate) - 1
      ELSE
        0
      END
    END AS Age
  FROM FeedbackTable
)
SELECT COUNT(*) AS [25To34] 
FROM AgeCTE 
WHERE (Age >= 25) AND (Age <= 34)

我将重复@Shnugo所说的,您应该在CONVERT语句中使用隐式格式参数,而不是使用VARCHAR存储日期。

整个查询工作正常,因为您没有尝试检索年龄列,因此它被忽略,完全没有计算,因为计算的输出是无用的。你有很多反馈领域的转换-你说你不明白问题出在哪里是什么意思?问题在于“反馈”列中的数据-某些值不是有效日期。整个查询正在工作,因为您没有尝试检索“年龄”列,因此它被忽略,完全没有计算,因为计算的输出是无用的。你有很多反馈领域的转换-你说你不明白问题出在哪里是什么意思?问题在于“反馈”列中的数据-某些值不是有效日期。TRY_CONVERT是SQL Server 2012的新获取程序,操作标签也是SQL Server 2008。@ahmedabdelqader,我知道,我自己的答案中有2012+-提示。检查2012+服务器上的数据完整性就足够了……感谢您的回答。我知道以字符串格式存储日期不是一个好方法。但该系统的要求是,几乎不可避免地要有它。我通过在查询中使用ISDATE函数消除了错误。这是一个愚蠢的错误,浪费了很多时间。无论如何谢谢你!TRY_CONVERT是SQL Server 2012的一个新获取程序,OP也标记为SQL Server 2008。@ahmedabdelqader,我知道,我自己的答案中有2012+-提示。检查2012+服务器上的数据完整性就足够了……感谢您的回答。我知道以字符串格式存储日期不是一个好方法。但该系统的要求是,几乎不可避免地要有它。我通过在查询中使用ISDATE函数消除了错误。这是一个愚蠢的错误,浪费了很多时间。无论如何谢谢你!谢谢你的回答。我昨晚确实用了你所说的ISDATE函数解决了这个问题。但我会接受你的答案,这会给你带来荣誉。谢谢你的回答。我昨晚确实用了你所说的ISDATE函数解决了这个问题。但我会接受你的答案,给你学分。