0

在表中users,我有一列usernamedatatype 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(即使我ltrimrtrim更新前的单个字符值)会发生什么情况?

为什么我必须将我CONTEXT_INFO的总字节数填充到 127 个字节,而不是 128 个字节?对于超过 127 的每个字符,从最初设置的值中截断 1 个字符CONTEXT_INFO

注意:ANSI_PADDING 已启用

4

2 回答 2

1

在您的代码中:

declare @user varchar(50) = left(@context, 50)
UPDATE users set username = ltrim(rtrim(@user)) WHERE id = 1

您定义@user为 50 个字符。由于它CONTEXT_INFO本身是 128 个字节,因此 的内容@user将是B由 49 个空字符填充的字母CHAR(0)LTRIM()并且RTRIM()不会删除不是空格的空字符,因此它们对@user.

如果你想删除NULL字符,你可以试试这个(假设你使用的是 SQL Server 2005 或更高版本):

UPDATE users SET username = REPLACE(@user, char(0), '')
于 2016-01-22T01:36:44.470 回答
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。

于 2021-02-15T09:38:10.710 回答