Sql server 我的动态SQL语句中存在转换错误
我正在尝试构建动态SQL语句,出现以下错误: 从字符串转换日期和/或时间时,转换失败 声明如下:Sql server 我的动态SQL语句中存在转换错误,sql-server,stored-procedures,dynamic-sql,Sql Server,Stored Procedures,Dynamic Sql,我正在尝试构建动态SQL语句,出现以下错误: 从字符串转换日期和/或时间时,转换失败 声明如下: DECLARE @param NVARCHAR(128) = '2451,2452' DECLARE @sql NVARCHAR(MAX) DECLARE @userid NVARCHAR(50) = 'myUserId' SET @sql = N'UPDATE MyLogTable SET MessageType = ''F'', LastUpdatedBy = ''' + @userId +
DECLARE @param NVARCHAR(128) = '2451,2452'
DECLARE @sql NVARCHAR(MAX)
DECLARE @userid NVARCHAR(50) = 'myUserId'
SET @sql = N'UPDATE MyLogTable SET MessageType = ''F'', LastUpdatedBy = ''' + @userId + ''',
LastUpdated = ''' + GETDATE() + ' WHERE id IN(' + @param + ')
这句话怎么了?日期末尾缺少一个结束撇号:
LastUpdated = ''' + GETDATE() + ' WHERE...
将生成以下SQL:
LastUpdated = ' 2019-12-08 11:15 WHERE...
请注意,这会将LastUpdated值更新为生成动态SQL的时间和日期,这通常是一个非常好的精度,但更准确的语句是将GETDATE()
作为动态查询本身的一部分(这也使SQL语句更简单、更不容易出错。在执行动态SQL之前,您应该始终打印它,以确保没有此类错误。
此外,您正在将参数连接到SQL语句中,使其容易受到SQL注入攻击 当我们谈到这个话题时,我建议阅读我的博客文章-我在这里解释如何安全地创建动态SQL语句以避免SQL注入的危险,以及如何生成可读、可维护的动态SQL语句的另一个技巧 更安全的动态SQL是:
DECLARE @param NVARCHAR(128) = '2451,2452',
@sql NVARCHAR(4000),
@userid NVARCHAR(50) = 'myUserId',
@Tab nchar(1) = NCHAR(9),
@LineBreak nchar(2) = NCHAR(13) + NCHAR(10);
SET @sql =
N'UPDATE MyLogTable '+ @LineBreak +
N'SET MessageType = ''F'', '+ @LineBreak +
N'LastUpdatedBy = @userId , '+ @LineBreak +
N'LastUpdated = GETDATE() '+ @LineBreak +
N'WHERE id IN(' + @param + ')';
PRINT @SQL
--EXEC sp_ExecuteSql @Sql, N'@userid nvarchar(50)', @userid
注意这仍然不能处理@param
连接。
由于这是运算符中的,因此我建议使用表值参数而不是逗号分隔的字符串
假设一个名为Ids的用户定义表类型具有单个id int列:
CREATE TYPE dbo.Ids AS Table(Id int)
GO
以下是安全的动态SQL语句的外观:
DECLARE @param dbo.Ids;
INSERT INTO @Param (Id) Values (2451),(2452);
DECLARE @sql NVARCHAR(4000),
@userid NVARCHAR(50) = 'myUserId',
@Tab nchar(1) = NCHAR(9),
@LineBreak nchar(2) = NCHAR(13) + NCHAR(10);
SET @sql =
N'UPDATE MyLogTable '+ @LineBreak +
N'SET MessageType = ''F'', '+ @LineBreak +
N'LastUpdatedBy = @userId , '+ @LineBreak +
N'LastUpdated = GETDATE() '+ @LineBreak +
N'WHERE id IN(SELECT Id FROM @param)';
PRINT @SQL
--EXEC sp_ExecuteSql @Sql, N'@userid nvarchar(50), @param dbo.Ids', @userid
我已经根据语法和错误消息添加了SQL Server标记。