13

我正在尝试使用CONTEXT_INFO将用户代码从存储过程传递到 DELETE 触发器以进行表审计。

一切正常,但是我注意到保存在审计表中的用户代码的长度不正确。

以这个脚本为例...

declare @userCode varchar(50)
set @userCode = 'TestUser'

declare @binary_userCode varbinary(128)
set @binary_userCode = cast(@userCode as varbinary(128))
set CONTEXT_INFO @binary_userCode

declare @temp_userCode varchar(50)
set @temp_userCode = (select cast(CONTEXT_INFO() as varchar(50)))

--set @temp_userCode = rtrim(ltrim(@temp_userCode))

select @userCode, len(@userCode), @temp_userCode, len(@temp_userCode)

set CONTEXT_INFO 0x

结果:

len(@userCode) = 8

长度(@temp_userCode)= 50

为什么@temp_userCode变量以 50 的长度返回,我怎样才能将它修剪回原来的长度以正确存储它?

更多的信息:

运行 SQL Server 2005,但该解决方案需要在 2005 及以后的所有版本中工作。

4

4 回答 4

8

当分配给CONTEXT_INFO它时,它会用空字节填充0x00到 128 个字节的长度并变为0x5465737455736572000000...

您可以使用

REPLACE(CAST(CONTEXT_INFO() AS varchar(128)) COLLATE Latin1_General_100_BIN , 
        0x00, 
        '')
于 2012-02-24T16:56:12.793 回答
4

它被填充CHAR(0)。尝试:

set @temp_userCode = REPLACE(@temp_userCode COLLATE Latin1_General_BIN, CHAR(0), '');

编辑:添加了一个明确的COLLATE条款,虽然现在我觉得我在从马丁那里偷东西。)

于 2012-02-24T17:02:30.220 回答
2

试试这个,它适用于 SQL Server 2005:

select cast(substring(CONTEXT_INFO(), 1, charindex(0x00, CONTEXT_INFO())-1) as varchar(128));

无需考虑凌乱的排序规则:-)

于 2014-09-26T11:03:01.117 回答
0

除非您指定排序规则,否则替换将在不同的 SQL 服务器安装上随机失败:

REPLACE(CAST(CONTEXT_INFO() AS varchar(128)) COLLATE Latin1_General_100_BIN , 0x00, '')

SQL Server 有两种不同的行为,具体取决于它的安装方式:

  • 使用 SQL 排序规则时替换成功。
  • 使用 Windows 排序规则时替换不成功。

这种行为是在将近 7 年前提交给微软的:

问:当尝试用 replace() 替换 NUL 字符时,这个值有 SQL 排序规则,但没有 Windows 排序规则。

答:这是因为 0x0000 是 Windows 排序规则中的未定义字符。在比较、排序和模式匹配期间,所有未定义的字符都会被忽略。所以搜索'a' + char(0) 真的是在搜索'a',而搜索char(0) 相当于空字符串。

处理未定义字符的方式有点混乱,但这是 Windows 定义的对它们进行排序的方式,并且 SQL Server 符合通用的 Windows API。

在 SQL 排序规则中,没有未定义字符的概念。每个代码点都分配了一个权重,这就是我们在那里看不到问题的原因。

于 2014-07-24T09:33:50.243 回答