直接传递值时抛出转换错误

时间:2018-03-15 14:25:04

标签: sql sql-server tsql

此代码在直接传递值时会引发错误,但如果使用参数传递值则不会显示任何错误。

- 它会抛出错误

DECLARE @sql NVARCHAR(4000)
DECLARE @ID INT=1234
SET @sql = N'select 
                [count]
            FROM dbo.Table_1 AS t
            JOIN dbo.table_2 AS t2 ON t.store_number = t2.store_number
            AND  t2.[year] = 17
            AND  t2.week_of_year = 6
            AND  t2.day_of_week = 2
            WHERE t.RC_ID = @ID'
    EXEC sp_executesql @sql

- 它会抛出错误

select 
    [count]
FROM dbo.Table_1 AS t
JOIN dbo.table_2 AS t2 ON t.store_number = t2.store_number
AND  t2.[year] = 17
AND  t2.week_of_year = 6
AND  t2.day_of_week = 2
WHERE t.ID = 1234

-- IT WORKS

DECLARE @sql
DECLARE @ID INT
SET @ID = 1234

select 
    [count]
FROM dbo.Table_1 AS t
JOIN dbo.table_2 AS t2 ON t.store_number = t2.store_number
AND  t2.[year] = 17
AND  t2.week_of_year = 6
AND  t2.day_of_week = 2
WHERE t.ID = @ID

错误是:

  

Msg 245,Level 16,State 1,Line 1转换时转换失败   varchar值' TEST'数据类型int。

但是没有像'测试'在表中。

3 个答案:

答案 0 :(得分:0)

您作为整数进行比较的一个值包含错误的值:

select t2.*
from table_2 t2
where try_convert(int, year) is null or try_convert(int, week_of_year) is null or
      try_convert(int, day_of_week) or try_convert(int, id) is null;

是否发生错误取决于执行计划。

答案 1 :(得分:0)

您要过滤的某个表列不是数字数据类型。当你这样做

WHERE VarcharColumn = 1

SQL Server引擎将始终尝试将最复杂的类型转换为最简单的类型,在这种情况下,“1”是一个整数,VarcharColumn是VARCHAR,因此引擎将尝试转换存储的所有值在按值1过滤之前,在VarcharColumn中为整数。由于存储的至少一个值不是整数(“TEST”),因此转换失败并弹出该消息。

你有2个解决方案:

  • 验证并修复这些列中的所有值,使它们实际上是数字,并将数据类型更改为相应的值。
  • 比较相同的类型。 WHERE Column = '1'

当然,请务必检查数据类型。

同样在您的dynamicSQL查询中,@ID的声明必须在您的脚本中(它也缺少初始值)。

DECLARE @sql NVARCHAR(4000)
SET @sql = N'
    DECLARE @ID INT = 1

    select 
        [count]
    FROM dbo.Table_1 AS t
    JOIN dbo.table_2 AS t2 ON t.store_number = t2.store_number
    AND  t2.[year] = 17
    AND  t2.week_of_year = 6
    AND  t2.day_of_week = 2
    WHERE t.RC_ID = @ID'

EXEC sp_executesql @sql

错误弹出“有时”的原因是因为语句的不同形式使执行计划以不同的顺序执行。如果它首先尝试将varchar值转换为int,则它将失败。如果它试图将int值转换为varchar(例如),则它不会失败。

要找到问题,请尝试以下方法:

SELECT
    *
FROM
    dbo.Table_1 AS T
WHERE
    CONVERT(VARCHAR(200), T.store_number) = 'Test' OR
    CONVERT(VARCHAR(200), T.ID) = 'Test'

SELECT
    *
FROM
    dbo.table_2 AS T
WHERE
    CONVERT(VARCHAR(200), T.store_number) = 'Test' OR
    CONVERT(VARCHAR(200), T.[year]) = 'Test' OR
    CONVERT(VARCHAR(200), T.week_of_year) = 'Test' OR
    CONVERT(VARCHAR(200), T.day_of_week) = 'Test'

答案 2 :(得分:0)

从我看到你试图在sp_executeSQL中使用参数(@id)而不传递它。快速修复就是做那样的事情

DECLARE @sql NVARCHAR(4000)
DECLARE @ID INT = 10
SET @sql = N'select 
            [count]
        FROM dbo.Table_1 AS t
        JOIN dbo.table_2 AS t2 ON t.store_number = t2.store_number
        AND  t2.[year] = 17
        AND  t2.week_of_year = 6
        AND  t2.day_of_week = 2
        WHERE t.RC_ID = ' + cast(@ID as nvarchar(20))
EXEC sp_executesql @sql

希望这有帮助

相关问题