动态SQL语句中使用LIKE通配符查询无结果的问题排查
问题分析与解决
你遇到的核心问题是动态SQL中错误地将参数名当作字符串字面量处理了,导致实际执行的查询是在匹配Forename等于'@FirstName%'的记录,而不是用你传入的Test加上通配符去模糊匹配。
具体错误点:
- 拼接
@Search时,你额外添加了单引号,把@FirstName变成了字符串的一部分,而不是作为参数引用。 @Params中定义的参数长度和存储过程的@FirstName长度不一致(存储过程是varchar(100),@Params写的是varchar(300)),虽然不致命,但容易引发潜在问题。
修正后的存储过程代码
CREATE PROCEDURE dbo.uspFilter @FirstName varchar(100) = null, @Debug bit = 1 AS DECLARE @SQL nvarchar(max); DECLARE @Params nvarchar(max); -- 统一参数定义,和存储过程参数长度保持一致 SELECT @Params = N'@FirstName varchar(100) = null' SELECT @SQL = N'SELECT * FROM [Table] WHERE 1=1' IF @FirstName IS NOT NULL -- 直接在动态SQL中使用参数+通配符,不需要额外拼接字符串 SELECT @SQL = @SQL + N' AND Forename LIKE @FirstName + ''%''' IF @Debug = 1 PRINT @SQL EXEC sp_executeSQL @SQL, @Params, @FirstName = @FirstName; GO -- 测试调用 EXEC dbo.uspFilter @FirstName = 'Test', @Debug = 1; GO
调试输出的正确语句:
SELECT * FROM [Table] WHERE 1=1 AND Forename LIKE @FirstName + '%'
这样执行时,sp_executesql会正确把@FirstName替换为你传入的Test,实际执行的逻辑是Forename LIKE 'Test%',就能返回匹配的结果了。
后续多参数扩展建议:
- 每个条件分支都采用参数化拼接的方式,不要直接把用户输入拼到SQL语句里,避免SQL注入风险。
- 继续保留
WHERE 1=1的结构,这样添加多个条件时不需要判断是否是第一个条件,直接加AND 条件即可。 - 调试时可以打印最终的动态SQL语句,确认参数引用正确,同时借助
sp_executesql的参数传递机制保证安全性。
内容的提问来源于stack exchange,提问作者David Austin
相关产品推荐
相关产品推荐

