2012-02-24 64 views
9

我試圖使用CONTEXT_INFO將用戶代碼從存儲過程傳遞到DELETE觸發器以進行表審計。將CONTEXT_INFO轉換爲varchar並生成長度

它一切正常,但我注意到,在審計表中保存的用戶代碼的長度不正確。

取本腳本作爲一個例子...

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,如何將其修剪回原始長度以便將其存儲ctly?

更多信息:

運行SQL Server 2005,但該解決方案需要在2005年以後的所有版本的工作。

回答

6

當被分配CONTEXT_INFO它被填充了與空字節長度爲0x00爲128字節,併成爲0x5465737455736572000000...

您可以使用

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

這工作,我不得不整理更改爲SQL_Latin1_General_CP437_BIN。這是基於試驗和錯誤,但這並沒有給我很多信心。我該如何澄清我應該使用的排序規則? – 2012-02-24 17:14:10

+0

@Poz - 你沒有在你的問題中聲明SQL Server版本。如果在2008年之前,「100」排序規則將不可用。 – 2012-02-24 17:15:33

+0

道歉。我正在運行2005年,但它也需要適用於以上所有版本。 – 2012-02-24 17:18:12

3

它獲取與CHAR(0)填充。嘗試:

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

編輯:增加了一個明確的COLLATE條款,但現在我覺得我從馬丁偷。)

+0

+1我在回答中使用了顯式的轉換和collat​​e子句[因爲這個問題](https://connect.microsoft.com/SQLServer/feedback/details/708179/indefinite-hang-with-replace-statement-on -varbinary-max),但它只出現在varbinary(max)'上。 – 2012-02-24 17:12:50

+0

這個解決方案對我不起作用,長度仍然是50.由於SQL 2005或許? – 2012-02-24 17:21:03

+0

其實我發現兩個運行9.00.3042,其他9.00.4211,它的工作 - 兩個長度顯示8. – 2012-02-24 17:21:59

0

替換上的SQL Server unless you specify the collation不同的安裝將隨機失敗:

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

SQL服務器有兩個不同的行爲,取決於它是如何安裝的:

  • 使用SQL歸類時替換成功。
  • 使用Windows排序規則時替換失敗。

這種行爲被提交給微軟即將過去7年前:

問:當嘗試一個替換替換(NUL字符 ),這部作品是 值的SQL排序規則,但不是 Windows排序規則。

答:這是由於這樣的事實,爲0x0000 是Windows 排序規則未定義的字符。在比較,排序, 和模式匹配過程中,所有未定義字符 都將被忽略。因此搜索 'a'+ char(0)實際上是在搜索 'a',並且搜索char(0)是 等效於空字符串。

處理不確定的字符 的方式是有點混亂,但是這是Windows系統定義對它們進行排序, 和SQL Server與 一般的Windows API符合的 方式。

在SQL排序規則中,沒有未定義字符的概念 。每個代碼 點都分配了一個權重,這就是爲什麼 我們在那裏看不到問題。

2

試試這個,它爲我的SQL Server 2005:

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

沒有凌亂的排序規則考慮然而:-)