SQL Server动态SQL报错(疑单引号问题):请求协助排查修正
排查动态SQL中的语法错误(Msg 156)
嘿,我一眼就瞅出你代码里的问题啦——你猜的没错,就是单引号惹的祸!咱们一步步来拆解和修复:
错误根源
你的动态SQL拼接时犯了两个小问题:
- 单引号缺失:
@policy是带通配符的字符串值('TTY%'),但直接拼接后,SQL语句里会变成like TTY%——没有单引号包裹的话,SQL会把TTY当成列名/标识符,而非字符串常量,这直接触发了Incorrect syntax near the keyword 'or'的语法错误。 - 笔误:第二个
when分支里的第三个条件写成了[policy2] like,应该是[policy3] like,虽然这不会触发当前错误,但会导致逻辑判断不准确。
修复方案
方案1:快速修复字符串拼接(不推荐,存在SQL注入风险)
给@policy的前后加上转义的单引号(SQL里用两个单引号表示一个实际的单引号),同时修正笔误:
Declare @policy NVARCHAR(MAX); Declare @account_list NVARCHAR(MAX); Declare @sql NVARCHAR(MAX); Set @policy ='TTY%'; Set @account_list='18000,19000'; Set @sql = 'Select case when [Debit_Account] in ('+@account_list+') and ([policy1] like '''+@policy+''' or [policy2] like '''+@policy+''' or [policy3] like '''+@policy+''') then -[Amount] when [Credit_Account] in ('+@account_list+') and ([policy1] like '''+@policy+''' or [policy2] like '''+@policy+''' or [policy3] like '''+@policy+''') then [Amount] else 0 end as [Amount] from CTGS where [Debit_Account] in ('+@account_list+') or [Credit_Account] in ('+@account_list+')'; EXEC sp_executesql @sql;
方案2:参数化动态SQL(强烈推荐,安全且易维护)
直接拼接字符串不仅容易出语法错误,还会带来SQL注入风险(比如恶意用户传入18000); drop table CTGS;--作为@account_list值)。用参数化查询可以彻底解决这些问题:
Declare @policy NVARCHAR(MAX); Declare @account_list NVARCHAR(MAX); Declare @sql NVARCHAR(MAX); Set @policy ='TTY%'; Set @account_list='18000,19000'; -- 使用STRING_SPLIT拆分逗号分隔的账号列表,同时将@policy作为参数传入 Set @sql = 'Select case when [Debit_Account] in (select value from string_split(@account_list, '','')) and ([policy1] like @policy or [policy2] like @policy or [policy3] like @policy) then -[Amount] when [Credit_Account] in (select value from string_split(@account_list, '','')) and ([policy1] like @policy or [policy2] like @policy or [policy3] like @policy) then [Amount] else 0 end as [Amount] from CTGS where [Debit_Account] in (select value from string_split(@account_list, '','')) or [Credit_Account] in (select value from string_split(@account_list, '',''))'; -- 传递参数给sp_executesql EXEC sp_executesql @sql, N'@policy NVARCHAR(MAX), @account_list NVARCHAR(MAX)', @policy = @policy, @account_list = @account_list;
注:
STRING_SPLIT适用于SQL Server 2016及以上版本,如果你的版本更低,可以用自定义的字符串拆分函数代替。
内容的提问来源于stack exchange,提问作者Dinh Quang Tuan
相关产品推荐
相关产品推荐

