sql - 即使成功更新后,T-SQL 过程、标量变量也会出错

标签 sql sql-server tsql stored-procedures dynamic-sql

--sp_executesql version
    --SET @SQLQUERY = 'UPDATE @TableName SET Brief = @Brief,
    --               [Full] = @Full,                        
    --               CreatedBy = @CreatedBy,
    --               Department = @Department,
    --               Answer = @Answer WHERE Id=@Id';
 --SET @ParamDefinition=N'@TableName nvarchar(50),@Brief nvarchar(50),@Full nvarchar(MAX),@CreatedBy varchar(256),@Department varchar(256),@Answer nvarchar(MAX),@Id int' 
--  exec sp_executesql @SQLQUERY,@ParamDefinition,@TableName,@Brief,@Full,@CreatedBy,@Department,@Answer,@Id; 

-- exec version
SET @SQLQUERY = 'UPDATE ' + @TableName + ' SET  
                     Brief ='+ @Brief+',
                     [Full] ='+ @Full+',                        
                     CreatedBy ='+ @CreatedBy+',
                     Department ='+ @Department+',
                     Answer ='+@Answer+' WHERE Id='+CAST(@Id as nvarchar(10))

print @SQLQUERY; 
EXEC (@SQLQUERY)

我使用了 EXECsp_executesql 过程来执行动态查询,但都失败了。

如果是 EXEC,则动态查询未设置为 @SQLQUERY 变量(调试后可见),如果是 sp_executesql I尽管数据库已更新并且我已经将所有内容传递给它,但出现标量变量错误。

最佳答案

案例非常简单。您无法在 UPDATE 中参数化表/列名称声明:

SET @SQLQUERY = 'UPDATE @TableName       --here is problem
                 SET    Brief = @Brief, 
                        [Full] = @Full,                        
                        CreatedBy = @CreatedBy,
                        Department = @Department,
                        Answer = @Answer 
                 WHERE Id=@Id';


SET @ParamDefinition=N'@TableName nvarchar(50),@Brief nvarchar(50), 
                       @Full nvarchar(MAX), @CreatedBy varchar(256),
                       @Department varchar(256),@Answer nvarchar(MAX),@Id int' 

EXEC dbo.sp_executesql @SQLQUERY,@ParamDefinition,
                        @TableName,@Brief,@Full,
                        @CreatedBy,@Department,@Answer,@Id;

使用替换:

SET @SQLQUERY = N'UPDATE <tab_name> 
                  SET Brief     = @Brief, 
                     [Full]     = @Full,                        
                     CreatedBy  = @CreatedBy,
                     Department = @Department,
                     Answer     = @Answer 
                  WHERE Id = @Id';

SET @SQLQUERY = REPLACE(@SQLQUERY, '<tab_name>', QUOTENAME(@TableName));

SET @ParamDefinition=N'@Brief nvarchar(50),@Full nvarchar(MAX),
                       @CreatedBy varchar(256),@Department varchar(256),
                       @Answer nvarchar(MAX),@Id int';

EXEC [dbo].[sp_executesql] @SQLQUERY,
                           @ParamDefinition,
                           @Brief,@Full,@CreatedBy, @Department,@Answer,@Id;

注释:

  • 表名称应具有 SYSNAME 数据类型。
  • 最好使用 QUOTENAME 引用标识符(以避免潜在的 SQL 注入(inject)攻击)。
  • 我猜 @CreatedBydatetime,这就是为什么我不明白为什么它作为 varchar(256) 传递的原因。
  • 最好以 ; 结束每个语句。。在未来的版本中,这将是强制性的。

关于sql - 即使成功更新后,T-SQL 过程、标量变量也会出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36660853/

相关文章:

mysql - SQL 查询返回列值的实例但返回其他字段

sql - 表变量在表中的值函数

sql-server - TSQL:查询之间的日期 - 忽略时间

sql - 计算在行类型 2 日期之间找到行类型 1 的次数

c# - EF Core/Sqlite 一对多关系因唯一索引约束而失败

MySQL条件插入导致错误代码1364 : "Field doesn' t have a default value"

asp.net - 您使用什么工具来提高编码效率和整体效率

c# - 在 Entity Framework 中将 1 映射到 0-1

sql - 找出模式的序号

sql-server - 我如何在 where 语句中使用 Count(*)?