Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 我的动态SQL语句中存在转换错误_Sql Server_Stored Procedures_Dynamic Sql - Fatal编程技术网

Sql server 我的动态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 +

我正在尝试构建动态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 + ''',
        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标记。