为啥 sp_executesql 需要 ntext/nchar/nvarchar 而不是 text/char/varchar?

Posted

技术标签:

【中文标题】为啥 sp_executesql 需要 ntext/nchar/nvarchar 而不是 text/char/varchar?【英文标题】:Why does sp_executesql REQUIRE ntext/nchar/nvarchar as opposed to text/char/varchar?为什么 sp_executesql 需要 ntext/nchar/nvarchar 而不是 text/char/varchar? 【发布时间】:2012-09-22 01:41:00 【问题描述】:

为什么 sp_executesql 需要 ntext/nchar/nvarchar 参数和语句而不是 text/char/varchar?

我了解如何解决此问题(通过将所有语句/参数声明为 nvarchar),但为什么 Microsoft 会强制执行此操作?有什么好处?

【问题讨论】:

【参考方案1】:

我不确定这是出于特定于该程序的任何特定原因而强制执行的。另一个对数据类型很挑剔的系统存储过程的例子是sp_trace_create.

这不仅需要nvarchar 用于@tracefile 参数,而且参数@maxfilesize 必须作为'bigint' 传递,并且它不接受始终能够正确转换的文字整数。

这失败了

DECLARE @TraceID int
EXEC sp_trace_create @TraceID OUTPUT, 0, N'X:\Foo', 1, NULL 

成功了

DECLARE @TraceID int
DECLARE @x bigint = 1

EXEC sp_trace_create @TraceID OUTPUT, 0, N'X:\Foo', @x, NULL 

这两个都显示为master 数据库中的系统扩展存储过程。我假设这些扩展存储过程的调用机制与常规存储过程的调用机制不同,因此 SQL Server 不会隐式转换参数。

sp_executesql 像这样强制执行nvarchar 不一定是坏事。动态 SQL 可能出现的一个潜在问题是,如果以nvarchar 的形式提供字符串,然后对其进行清理然后强制转换为varchar,则转换可能会打开 SQL 注入机会。 An example of that is in my answer here.

【讨论】:

但 OTOH xp_cmdshell 也是一个扩展存储过程,接受 varchar(8000)nvarchar(4000)

以上是关于为啥 sp_executesql 需要 ntext/nchar/nvarchar 而不是 text/char/varchar?的主要内容,如果未能解决你的问题,请参考以下文章

如何将 sp_executesql 结果转换为变量?

[转]使用exec和sp_executesql动态执行SQL语句

sp_executesql vs 用户定义的标量函数

当使用 sp_executesql 作为过滤器时,保护 t-sql 动态代码的最佳方法是啥

EXEC与sp_executesql的区别及应用

SQLServer : EXEC和sp_executesql的区别