Приведение CONTEXT_INFO к varchar и полученная длина - PullRequest
11 голосов
/ 24 февраля 2012

Я пытаюсь использовать 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

len (@temp_userCode) = 50

Почему переменная @temp_userCode возвращается с длиной 50, и как я могу обрезать ее до ее первоначальной длины для сохраненияэто правильно?

Дополнительная информация:

Запуск SQL Server 2005, однако решение должно работать во всех версиях 2005 года.

Ответы [ 4 ]

7 голосов
/ 24 февраля 2012

При присвоении CONTEXT_INFO он дополняется нулевыми байтами 0x00 до 128 байтов в длину и становится 0x5465737455736572000000...

Вы можете использовать

REPLACE(CAST(CONTEXT_INFO() AS varchar(128)) COLLATE Latin1_General_100_BIN , 
        0x00, 
        '')
3 голосов
/ 24 февраля 2012

Он дополняется CHAR(0). Попробуйте:

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

( EDIT : добавлено явное предложение COLLATE, хотя теперь я чувствую, что краду у Мартина.)

2 голосов
/ 26 сентября 2014

Попробуйте, это работает для меня на SQL Server 2005:

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

Нет грязных сопоставлений, чтобы рассмотреть: -)

0 голосов
/ 24 июля 2014

Произойдет случайный сбой замены на разных установках сервера SQL , если вы не укажете параметры сортировки :

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

SQL-сервер имеет два различных поведения в зависимости от того, как он установлен:

  • Замена успешно выполняется при использовании сортировки SQL.
  • Замена не удалась, если используется сортировка Windows.

Такое поведение было передано в Microsoft более 7 лет назад:

Q: При попытке заменить символ NUL с replace (), это работает значение имеет сортировку SQL, но не Windows сортировка.

A: Это связано с тем, что 0x0000 является неопределенным символом в Windows Параметры сортировки. Все неопределенные символы игнорируются при сравнении, сортировке, и сопоставление с образцом. Так что в поисках 'a' + char (0) действительно ищет "A", и поиск символа (0) эквивалент пустой строки.

Способ обработки неопределенного символа немного сбивает с толку, но это способ, которым Windows определил их сортировку, и SQL Server соответствует общий Windows API.

В сопоставлении SQL нет понятия неопределенного персонажа. Каждый код баллу присваивается вес, поэтому мы не видим там проблемы.

...