SSMS与SQLCMD中使用context_info输出不一致问题排查
问题描述
用户编写的T-SQL代码如下:
declare @DBNAAM varbinary(128) = cast((select DB_NAME() as [Current Database]) + '_SINGLES-' as varbinary(128)); set context_info @DBNAAM; go print cast(context_info() as varchar(128)) + 'XTRA_NAME' go
在SSMS中运行时,输出符合预期:
TEST_T24TSV_SINGLES-XTRA_NAME
当前数据库名称为TEST_T24TSV_SINGLES。但使用SQLCMD执行同一脚本时,输出仅为:
T
将SSMS的输出复制到记事本时也仅显示T。用户使用context_info的原因是需要在多个GO语句后执行大量打印操作,且每个打印需为单行语句,而PRINT语句无法包含子查询。
问题原因
context_info是SQL Server中固定长度为128字节的varbinary类型变量。当向其赋值的内容长度不足128字节时,剩余字节会自动填充二进制空字符(0x00)。
将包含0x00的varbinary转换为varchar时,SQL Server会将第一个0x00视为字符串结束标记,导致后续内容被截断。这就是输出仅显示T的原因——转换后的字符串在某个位置遇到了0x00,提前终止。
解决方法
转换context_info()为varchar时,先移除其中的二进制空字符即可。修改后的代码如下:
declare @DBNAAM varbinary(128) = cast((select DB_NAME() as [Current Database]) + '_SINGLES-' as varbinary(128)); set context_info @DBNAAM; go print REPLACE(CAST(context_info() AS varchar(128)), CHAR(0), '') + 'XTRA_NAME' go
另一种方法是定位第一个空字符的位置,截取有效内容:
declare @DBNAAM varbinary(128) = cast((select DB_NAME() as [Current Database]) + '_SINGLES-' as varbinary(128)); set context_info @DBNAAM; go print SUBSTRING(CAST(context_info() AS varchar(128)), 1, CHARINDEX(CHAR(0), CAST(context_info() AS varchar(128))) - 1) + 'XTRA_NAME' go
两种方式都能避免空字符导致的截断问题,在SSMS和SQLCMD中均可输出完整的预期内容。
内容的提问来源于stack exchange,提问作者gilberke
相关产品推荐
相关产品推荐

