使用sp_executesql执行带方括号的TSQL动态SQL时参数未替换问题
问题原因
你遇到的问题是因为sp_executesql的参数无法直接替换方括号内的内容——SQL Server会将[@MyDBName]当作一个字面量的数据库名称,而不是将@MyDBName替换为传入的参数值。
解决方法
使用QUOTENAME()函数处理数据库名称,它可以自动为名称添加方括号,同时转义名称中的特殊字符(比如包含]、空格的数据库名),既兼容特殊名称又能防止SQL注入。
正确代码示例
DECLARE @DBName AS VARCHAR(40)='abc' DECLARE @DynSQL AS NVARCHAR(4000) -- 注意使用NVARCHAR,sp_executesql推荐使用Unicode字符串 SET @DynSQL = N'ALTER DATABASE ' + QUOTENAME(@MyDBName) + N' SET RESTRICTED_USER WITH ROLLBACK IMMEDIATE' EXECUTE sp_executesql @DynSQL, N'@MyDBName VARCHAR(99)', @MyDBName=@DBName
也可以提前用QUOTENAME()处理数据库名再拼接动态SQL,效果一致:
DECLARE @DBName AS VARCHAR(40)='abc' DECLARE @QuotedDBName AS NVARCHAR(128) = QUOTENAME(@DBName) DECLARE @DynSQL AS NVARCHAR(4000) SET @DynSQL = N'ALTER DATABASE ' + @QuotedDBName + N' SET RESTRICTED_USER WITH ROLLBACK IMMEDIATE' EXECUTE sp_executesql @DynSQL
有效性说明
QUOTENAME()会将输入字符串转换为合法SQL标识符:输入abc返回[abc],输入my db]返回[my db]]](自动转义内部的])。- 无论哪种写法,恶意输入都会被转义为无效数据库名称,不会触发SQL注入,同时完美兼容带特殊字符的数据库名。
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

