Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 从字符串错误转换日期和/或时间时,导致转换失败的CTE_Sql_Sql Server 2008_Tsql_Common Table Expression - Fatal编程技术网

Sql 从字符串错误转换日期和/或时间时,导致转换失败的CTE

Sql 从字符串错误转换日期和/或时间时,导致转换失败的CTE,sql,sql-server-2008,tsql,common-table-expression,Sql,Sql Server 2008,Tsql,Common Table Expression,我创建了一个非常简单的示例,展示了我在使用动态SQL进行更复杂的查询时遇到的一个问题,我无法理解为什么CTE会导致错误,而标准版本不是 使用CTE时出错: 从字符串转换日期和/或时间时,转换失败 我试图通过动态查询实现以下目标: 在本例中,标记与指定数据类型日期不匹配的记录。如果它们通过了该步骤,则稍后将对照查找表对其进行检查,以验证它们是否是我希望在指定范围内验证日期的值 -- Table Setup CREATE TABLE #ValidDate ( V INT IDENTI

我创建了一个非常简单的示例,展示了我在使用动态SQL进行更复杂的查询时遇到的一个问题,我无法理解为什么CTE会导致错误,而标准版本不是

使用CTE时出错:

从字符串转换日期和/或时间时,转换失败

我试图通过动态查询实现以下目标: 在本例中,标记与指定数据类型日期不匹配的记录。如果它们通过了该步骤,则稍后将对照查找表对其进行检查,以验证它们是否是我希望在指定范围内验证日期的值

 -- Table Setup
 CREATE TABLE #ValidDate 
 (
    V INT IDENTITY (1, 1) NOT NULL,
    VDate DATE NULL
 )

 INSERT INTO #ValidDate
 VALUES ('02/20/2014'), ('02/21/2014'), ('02/22/2014'), ('02/23/2014'), ('02/25/2014')

 CREATE TABLE #DatesToValidate 
 (
    I INT IDENTITY (1, 1) NOT NULL,
    IDate VARCHAR(30) NULL
 )

 INSERT INTO #DatesToValidate
 VALUES ('apple'), ('02/21/2014'), ('orange'), ('02/23/2014')

 CREATE TABLE #Errors
 (
    ID INT,
    Dates VARCHAR(30)
 )

 INSERT INTO #Errors
 SELECT *
 FROM #DatesToValidate
 WHERE ISDATE(IDate) <> 1
以下是CTE不工作的原因:

 ;WITH CTE AS
 (
    SELECT *
    FROM #DatesToValidate
    WHERE I NOT IN (    SELECT ID
                        FROM #Errors)
 )

 SELECT *
 FROM CTE
 WHERE IDate NOT IN (   SELECT VDate
                        FROM #ValidDate)

此特定部分失败,因为VDate是日期类型列,IDate是varchar。因此,您需要像castVDate一样将VDate强制转换为varchar30,如下所示

这里有小提琴演示吗

这样试试你的sql

;WITH CTE AS
 (
    SELECT *
    FROM DatesToValidate
    WHERE I NOT IN (    SELECT ID
                        FROM Errors)
 )

 SELECT *
 FROM CTE
 WHERE IDate NOT IN (SELECT cast(VDate as varchar(30))  <--- Cast Here
                        FROM ValidDate)

此特定部分失败,因为VDate是日期类型列,IDate是varchar。因此,您需要像castVDate一样将VDate强制转换为varchar30,如下所示

这里有小提琴演示吗

这样试试你的sql

;WITH CTE AS
 (
    SELECT *
    FROM DatesToValidate
    WHERE I NOT IN (    SELECT ID
                        FROM Errors)
 )

 SELECT *
 FROM CTE
 WHERE IDate NOT IN (SELECT cast(VDate as varchar(30))  <--- Cast Here
                        FROM ValidDate)
这说明了问题所在。两个版本都不能保证工作。如果交换中条件的顺序,则会导致转换失败

在这种情况下,和版本正常工作的原因是短路。当第一个条件失败时,第二个条件无法运行。这是SQL Server可以利用的优化。在这种情况下确实如此,所以你认为它是有效的

CTE版本不起作用,因为无法保证操作的顺序。SQL Server决定做一些不同的事情。也就是说,它试图将“苹果”作为日期进行评估

正确的解决方案是在比较之前进行强制转换。因为演员可能不起作用,你需要小心。为此,您应该使用SQL Server中的用例;它是保证顺序评估的唯一结构

那么,试试这个:

;WITH CTE AS
 (
    SELECT *
    FROM DatesToValidate
    WHERE I NOT IN (    SELECT ID
                        FROM Errors)
 )
 SELECT *
 FROM CTE
 WHERE (case when isdate(IDate) = 1 then cast(IDate as date)
        end) NOT IN (   SELECT VDate
                        FROM ValidDate)
这说明了问题所在。两个版本都不能保证工作。如果交换中条件的顺序,则会导致转换失败

在这种情况下,和版本正常工作的原因是短路。当第一个条件失败时,第二个条件无法运行。这是SQL Server可以利用的优化。在这种情况下确实如此,所以你认为它是有效的

CTE版本不起作用,因为无法保证操作的顺序。SQL Server决定做一些不同的事情。也就是说,它试图将“苹果”作为日期进行评估

正确的解决方案是在比较之前进行强制转换。因为演员可能不起作用,你需要小心。为此,您应该使用SQL Server中的用例;它是保证顺序评估的唯一结构

那么,试试这个:

;WITH CTE AS
 (
    SELECT *
    FROM DatesToValidate
    WHERE I NOT IN (    SELECT ID
                        FROM Errors)
 )
 SELECT *
 FROM CTE
 WHERE (case when isdate(IDate) = 1 then cast(IDate as date)
        end) NOT IN (   SELECT VDate
                        FROM ValidDate)

作为将来的参考,MySql与SQL Server是一个完全不同的DBMS,它们不应该被标记为相同的。您能提供关于不工作的更多详细信息吗?作为将来的参考,MySql与SQL Server是一个完全不同的DBMS,它们不应该被标记为相同的。您能提供关于不工作的更多详细信息吗?