0

テーブルには datatypeusersの列があります。テーブルにはレコードがありません。ユーザー名に新しいレコードを挿入します。以下は私が期待するものを返します:usernamevarchar(50)A

SELECT username, LEN(username) 
FROM users 
WHERE id = 1 -- returns: A, 1

ここまでは順調ですね。

次に、次の値を使用して、別のテーブルのトリガーからテーブル users を更新します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_tableI doのトリガーで:

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 になります (更新前の 1 文字の値ltrimであっても)。rtrim

CONTEXT_INFOまた、128 バイトではなく、合計 127 バイトにパディングする必要があるのはなぜですか? 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

@user50 文字と定義しました。CONTEXT_INFO自体は 128 バイトなので、 の内容は49個のヌル文字が埋め込まれ@userた文字になります。 空白ではないヌル文字は削除されないため、 には影響しません。BCHAR(0)LTRIM()RTRIM()@user

文字を削除したい場合は、NULLこれを試すことができます (SQL Server 2005 以降を使用していると仮定します):

UPDATE users SET username = REPLACE(@user, char(0), '')
于 2016-01-22T01:36:44.470 に答える