如何将INT数据库字段与VARCHAR类型进行比较

时间:2010-11-10 17:29:13

标签: sql sql-server tsql

我有以下存储过程,而不是编写完整的存储过程,但其中一些是:

@course int = null,
    SET @query = @query + 'Where course_id='+ cast(@course as varchar)

我想知道何时将@course转换为VARCHAR类型,而数据库中的course_id是INT类型 - 比较是如何进行的?

4 个答案:

答案 0 :(得分:6)

SQL Server中两种不同类型之间的比较如下:

  • 首先根据Data Type Precedence的规则比较两种类型的优先级:

      

    具有较低优先级的数据类型将转换为具有较高优先级的数据类型

  • 接下来,优先级较低的类型会转换为优先级较高的类型

  • 然后在具有较高优先级的类型的原始值与具有较低优先级的类型的转换值之间进行比较

为了便于讨论:通过将INT转换为VARCHAR来比较VARCHAR(优先级16,高位)和INT(优先级27,低位)然后比较两者。

在您的情况下,虽然没有发生转换,因为会发生的事情是@course值会附加到动态构造的@sql。不用说,这很糟糕。正确的解决方案是将@course作为参数传递给dymnamic SQL调用:

@course INT = null
...
 SET @query = @query + 'Where course_id= @course';
...
exec sp_executesql @sql, '@course int', @course;

这是:

  • 更快:参数化查询而不是硬编码值
  • 更安全:如果代码被重构并且@counter成为可以进行SQL注入的类型,则降低SQL注入的风险
  • 不易出错:没有传播NULL值的风险使整个@sql
  • 无效

答案 1 :(得分:4)

您发布的代码的基本原理是SQL Server需要更改数据类型以允许字符串连接发生。语句本身是一个字符串,提交给优化器,它将比较视为正确的数据类型 - INT到INT。

你可以测试&使用Management Studio / Toad / etc中的以下内容确认自己:

DECLARE @course INT
    SET @course = 1234

SELECT 'Where course_id='+ @course

这将失败,读取错误:

  

将varchar值'Where course_id ='转换为数据类型int。

时转换失败

...同时:

DECLARE @course INT
    SET @course = 1234

SELECT 'Where course_id='+ CAST(@course AS VARCHAR) AS output

...将返回:

output
---------------------
Where course_id=1234

还有其他方法可以接近dynamic SQL. I highly recommend reading this article -- The Curse and Blessings of Dynamic SQL -- on the subject

答案 2 :(得分:1)

您似乎混淆了比较(a = b)和作业(SET @a = b

VARCHARINT之间的比较中,前者始终被强制转换为后者,因此此查询将失败:

SELECT  1
WHERE   'ab' = 1

,因为'ab'无法投放到INT

在作业中,源值(b)始终强制转换为目标类型(@a):

DECLARE @av VARCHAR(100)
SET     @av = 1
GO

DECLARE @ai INT
SET     @ai = 'ab'
GO

由于INT始终可投放到VARCHAR,因此第一批将始终成功,而不像将VARCHAR投放到INT的第二批。

答案 3 :(得分:1)

在您的查询中,您实际上只是在构建另一个(动态)查询。所以,如果你有例如:

SET @course = 2
SET @query = 'SELECT * FROM Courses'
SET @query = @query + 'Where course_id='+ cast(@course as varchar)

@course的值转换为字符,附加到@query,最后是:

SELECT * FROM Courses Where course_id=2

这是完全有效的sql,无需在执行之前转换任何内容。