SQL Server 2014动态SQL报错:Line4附近语法错误'4'(Msg102)
问题原因
动态SQL拼接时,将日期变量转换为字符串后没有用单引号包裹,导致生成的SQL语句中日期值被当作数值表达式解析,引发语法错误。
比如假设@DATE的值是'2024-05-04',原代码拼接后会生成这样的片段:
CAST(2024-05-04 AS DATETIME)
SQL Server会把2024-05-04当作数值计算(2024减5减4=2015),但这不符合日期语法,因此报错"Incorrect syntax near '4'"。
解决方案
有两种可靠的修复方式:
方式1:给拼接的日期字符串添加单引号
修改动态SQL拼接部分,在日期字符串前后加上单引号(SQL里单引号需要用两个单引号转义),同时可以提前把日期转成字符串避免重复转换:
declare @table_name varchar(50) = '' ; declare @DATE_str varchar(30) = CAST(@DATE AS varchar(30)); select @table_name = iif((@YEAR is null) AND (@WEEK is null), 'table1', 'table2') declare @cmmnd varchar(max) = '' ; set @cmmnd = 'SELECT B.* INTO #temptable FROM [schema1].' + @table_name + ' B WITH (READUNCOMMITTED) WHERE B.Start <= CAST(''' + @DATE_str + ''' AS DATETIME) AND ISNULL(B.End, IIF(B.CrntR = 1, CAST(''' + @DATE_str + ''' AS DATETIME) + 1, CAST(''' + @DATE_str + ''' AS DATETIME) - 1)) > CAST(''' + @DATE_str + ''' AS DATETIME)'; EXEC (@cmmnd);
方式2:使用参数化动态SQL(更安全,避免注入)
用sp_executesql传递参数,无需手动拼接字符串,彻底避免语法错误和SQL注入风险:
declare @table_name varchar(50) = '' ; declare @param_definition nvarchar(500); select @table_name = iif((@YEAR is null) AND (@WEEK is null), 'table1', 'table2') declare @cmmnd nvarchar(max) = '' ; set @cmmnd = N'SELECT B.* INTO #temptable FROM [schema1].' + QUOTENAME(@table_name) + N' B WITH (READUNCOMMITTED) WHERE B.Start <= CAST(@DATE AS DATETIME) AND ISNULL(B.End, IIF(B.CrntR = 1, CAST(@DATE AS DATETIME) + 1, CAST(@DATE AS DATETIME) - 1)) > CAST(@DATE AS DATETIME)'; SET @param_definition = N'@DATE DATETIME'; EXEC sp_executesql @cmmnd, @param_definition, @DATE = @DATE;
这里用QUOTENAME处理表名,同时用参数传递@DATE,既安全又不会出现语法问题。
内容的提问来源于stack exchange,提问作者Hannah
相关产品推荐
相关产品推荐

