动态 SQL 查询 - 如何将 int 添加到代码中?

use*_*433 3 sql-server sql-injection dynamic-sql t-sql

考虑:

Declare @stringsvar varchar(1000)
Declare @Emp_id int 
DECLARE  @strvar SYSNAME = 'Employee_test'

SET @stringsvar = ('select * from' + ' ' + @strvar + ' where emp_id' + ' =' + @Emp_id)
Print @stringsvar
Run Code Online (Sandbox Code Playgroud)

上面的查询给出了如下所述的错误:

将 nvarchar 值 'select * from Employee_test where emp_id =' 转换为数据类型 int 时,消息 245,级别 16,状态 1,第 17 行转换失败。

在这种情况下需要做什么?

Eri*_*ing 13

George 的回答确实解决了您的问题,但它让您对SQL 注入攻击持开放态度

虽然将 an 转换INT为 aVARCHAR 11可能不会导致任何问题,但sysname相当于 an NVARCHAR 128,并且您可以在其中塞入大量额外代码。

为了使您的代码完全安全,您需要这样做:

DECLARE @stringsvar NVARCHAR(1000) = '';
DECLARE @Emp_id INT = 1;
DECLARE @strvar sysname = N'Employee_test';

SET @stringsvar = ( N'select * from ' 
                    + QUOTENAME(@strvar) 
                    + N' where emp_id' 
                    + N' = @iEmp_id' );

PRINT @stringsvar;
EXEC sys.sp_executesql @stringsvar, 
                       N'@iEmp_id INT', 
                       @iEmp_id = @Emp_id;
Run Code Online (Sandbox Code Playgroud)

使用sp_executesql发出参数化的动态 SQL,使用quotename使表名成为不可执行的代码是更安全的选择。

如需更多参考,我建议前往此处:动态 SQL 的诅咒和祝福


Geo*_*ios 6

问题归结为数据类型优先级

在这种情况下,INT数据类型具有更高的优先级,因此在这种情况下将数据类型VARCHAR转换(或尝试转换)为更高优先级的数据类型 ( INT)。

一个简单的 CASTVARCHAR应该可以解决这个问题,如下所示

 Declare @stringsvar varchar(1000)
 Declare @Emp_id int 
 DECLARE  @strvar SYSNAME = 'Employee_test'

SET @stringsvar = ('select * from' + ' ' + QUOTENAME(@strvar) + ' where emp_id' + ' =' + CAST(@Emp_id AS VARCHAR(11)))
Print @stringsvar
Run Code Online (Sandbox Code Playgroud)