如何在SQL LIKE通配符表达式中使用存储SQL逻辑的字符串变量
问题根本原因
你的写法错误将SQL逻辑运算符、多段判断条件拼接进了LIKE的匹配值变量中。数据库执行PERM.AgeFilter NOT LIKE @TrimmedAgeType时,只会把@TrimmedAgeType的完整内容当做普通匹配字符串处理,不会解析其中的AND为逻辑运算符,相当于你实际执行的判断逻辑是:匹配AgeFilter列的值是否包含%J%' AND PERM.AgeFilter NOT LIKE '%JS% 这一整段字符串。
几乎没有符合该匹配规则的记录,因此NOT LIKE判断永远为真,最终返回所有记录。而硬编码时SQL解析器会正常识别AND为逻辑运算符,所以结果符合预期。
解决方案
方案1:动态SQL执行(适配现有拼接逻辑)
你拼接好的完整条件片段需要通过动态SQL执行,才能让其中的逻辑运算符生效,改造示例如下:
DECLARE @SQL NVARCHAR(MAX); -- 拼接完整SQL语句 SET @SQL = N' SELECT * FROM #MembershipInfo #PSP INNER JOIN TRP_ME_PriceStructure PERM ON #PSP.MembershipPriceStructurePK = PERM.MembershipPriceStructurePK WHERE PERM.AgeFilter NOT LIKE ' + @TrimmedAgeType -- 执行动态SQL EXEC sp_executesql @SQL
如果需要改造为DELETE语句,直接替换查询部分即可:
DECLARE @SQL NVARCHAR(MAX); SET @SQL = N' DELETE #PSP FROM #MembershipInfo #PSP INNER JOIN TRP_ME_PriceStructure PERM ON #PSP.MembershipPriceStructurePK = PERM.MembershipPriceStructurePK WHERE PERM.AgeFilter NOT LIKE ' + @TrimmedAgeType EXEC sp_executesql @SQL
注意:如果
@AgeReference的取值来源包含用户输入,必须做防SQL注入校验,避免安全风险。
方案2:表变量存储过滤规则(更安全,无需动态SQL)
你是通过遍历年龄参考表生成的过滤规则,完全可以跳过字符串拼接步骤,直接用表变量存储所有需要排除的标识,通过关联判断实现过滤:
-- 存储所有要排除的年龄标识 DECLARE @ExcludeAgeTypes TABLE (AgeRef VARCHAR(100)); INSERT INTO @ExcludeAgeTypes(AgeRef) SELECT AgeReference FROM 你的年龄参考表; -- 过滤查询 SELECT * FROM #MembershipInfo #PSP INNER JOIN TRP_ME_PriceStructure PERM ON #PSP.MembershipPriceStructurePK = PERM.MembershipPriceStructurePK WHERE NOT EXISTS ( SELECT 1 FROM @ExcludeAgeTypes e WHERE PERM.AgeFilter LIKE '%' + e.AgeRef + '%' )
该方案不存在SQL注入风险,也不需要处理字符串拼接的收尾逻辑,稳定性更高。
内容的提问来源于stack exchange,提问作者naz786
相关产品推荐
相关产品推荐

