在表格users
中,我有一个数据类型为username
的列varchar(50)
。该表没有记录。我为用户名插入了A
的新记录。以下内容将返回我的期望:
SELECT username, LEN(username)
FROM users
WHERE id = 1 -- returns: A, 1
到目前为止一切顺利。
现在,我使用CONTEXT_INFO()
:
set @context = cast('B' as varbinary(128))
set CONTEXT_INFO @context
update some_other_table
set x = 'y'
where id = 97
在我some_other_table
的触发器中:
DECLARE @context VARCHAR(128)
SELECT
@context = CAST(CONTEXT_INFO() AS VARCHAR(128))
FROM
master.dbo.SYSPROCESSES
WHERE
SPID = @@SPID
DECLARE @user VARCHAR(50) = LEFT(@context, 50)
UPDATE users
SET username = LTRIM(RTRIM(@user))
WHERE id = 1
用户名正确设置为“B”,但现在返回50:
SELECT
username, LEN(username)
FROM
users
WHERE
id = 1 -- returns: B, 50
在填充上下文时,解决方案是:
set @context = cast('B' + replicate(' ', 126) as varbinary(128))
但为什么我需要这样做?
当我没有用空格填充CONTEXT_INFO
时发生的事情是使用其值进行更新将导致结果长度为50(即使我ltrim
和rtrim
单个更新前的字符值)?
为什么我必须将CONTEXT_INFO
填充到127个字节,而不是128个?对于超过127的每个字符,1个字符将从最初在CONTEXT_INFO
注意:启用了ANSI_PADDING
答案 0 :(得分:1)
在您的代码中:
declare @user varchar(50) = left(@context, 50)
UPDATE users set username = ltrim(rtrim(@user)) WHERE id = 1
您将@user
定义为50个字符。由于CONTEXT_INFO
本身是128个字节,因此@user
的内容将是由49个空B
个字符填充的字母CHAR(0)
。 LTRIM()
和RTRIM()
不会删除不是空格的空字符,因此它们对@user
没有影响。
如果要删除NULL
字符,可以尝试此操作(假设您使用的是SQL Server 2005或更高版本):
UPDATE users SET username = REPLACE(@user, char(0), '')
答案 1 :(得分:0)
我知道这个问题很老了,但是有两种方法可以检索 CONTEXT_INFO
:直接使用 CONTEXT_INFO()
或从 sys.dm_exec_sessions
检索。后者没有用“0”字符填充。
declare @c varbinary(128)
select @c = convert(varbinary(128), 'Test context')
set CONTEXT_INFO @c
go
-- option 1: padded with '0'
declare @value varchar(128)
select @value = convert(varchar(128), CONTEXT_INFO())
select @value context, len(@value) length
go
-- option 2: NOT padded with '0'
declare @value varchar(128)
select @value = convert(varchar(128), context_info)
from sys.dm_exec_sessions
where session_id = @@SPID
select @value context, len(@value) length
go
查询结果。
context length
--------------- -----------
Test context 128
(1 row affected)
context length
--------------- -----------
Test context 12
(1 row affected)
或者,从 SQL Server 2016 开始,您还可以使用 SESSION_CONTEXT()
,它允许您指定键值对,而不是单个二进制 blob。