2012-02-24 19 views
9

मैं संग्रहित प्रक्रिया से उपयोगकर्ता कोड को तालिका ऑडिटिंग उद्देश्यों के लिए एक DELETE ट्रिगर में पास करने के लिए CONTEXT_INFO का उपयोग करने का प्रयास कर रहा हूं।वर्चर को CONTEXT_INFO कास्टिंग और परिणामी लंबाई

यह सब ठीक काम करता है, हालांकि मैंने देखा कि ऑडिट तालिका में सहेजे गए उपयोगकर्ताकोड की लंबाई सही नहीं थी।

एक उदाहरण के रूप में इस स्क्रिप्ट ले लो ...

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 

परिणाम:

लेन (@userCode) = 8

लेन (@temp_userCode) = 50

@temp_userCode वैरिएबल 50 की लंबाई के साथ वापस आ रहा है, और मैं इसे वापस स्टोर करने के लिए इसकी मूल लंबाई पर कैसे ट्रिम कर सकता हूं ctly?

अतिरिक्त जानकारी:

चल रहा है SQL सर्वर 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 को मिलान बदलना पड़ा। यह परीक्षण और त्रुटि पर आधारित था हालांकि मुझे बहुत आत्मविश्वास से नहीं छोड़ता है। मैं कैसे स्पष्ट कर सकता हूं कि मुझे किस संयोजन का उपयोग करना चाहिए? –

+0

@Poz - आपने अपने प्रश्न में SQL सर्वर संस्करण नहीं बताया था। यदि 2008 से पहले '100' कॉलेशन उपलब्ध नहीं होंगे। –

+0

क्षमाप्रार्थी। मैं 2005 चला रहा हूं, हालांकि इसे इसके ऊपर के सभी संस्करणों के लिए भी उपयुक्त होना चाहिए। –

3

यह CHAR(0) साथ गद्देदार हो जाता है का उपयोग कर सकते हो जाता है। प्रयास करें:

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

(संपादित: एक स्पष्ट COLLATE खंड जोड़ा है, हालांकि अब मैं जैसे मैं मार्टिन से चोरी कर रहा हूँ महसूस करते हैं।)

+0

+1 मैं अपने उत्तर में एक स्पष्ट कास्ट और कोलेट क्लॉज का उपयोग करता हूं [इस समस्या के कारण] (https://connect.microsoft.com/SQLServer/feedback/details/708179/indefinite-hang-with-replace-statement-on -वर्बिनरी-अधिकतम) लेकिन यह केवल वैसे भी 'varbinary (अधिकतम)' के लिए दिखाई दिया। –

+0

यह समाधान मेरे लिए काम नहीं करता है, लंबाई अभी भी 50 है। एसक्यूएल 2005 के कारण शायद? –

+0

असल में मुझे दो - एक 9.00.3042 चल रहा है, दूसरा 9.00.4211, और यह काम करता है - दोनों लंबाई दिखाते हैं 8. –

0

बदलें बेतरतीब ढंग से एसक्यूएल सर्वर unless you specify the collation के विभिन्न प्रतिष्ठानों पर विफल हो जाएगा:

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

एसक्यूएल सर्वर, दो अलग अलग व्यवहार है कि यह कैसे स्थापित किया गया है पर निर्भर करता है:

  • SQL collation का उपयोग होने पर प्रतिस्थापन सफल होता है।
  • विंडोज कॉलेशन का उपयोग होने पर प्रतिस्थापन असफल रहा है। साल

यह व्यवहार Microsoft को प्रस्तुत की गई थी 7 लगभग पहले:

प्रश्न: जब कोशिश कर एक की जगह (के साथ एक NUL चरित्र की जगह), इस काम करता है मूल्य एक SQL गया है collation, लेकिन विंडोज collation नहीं।

एक: इस तथ्य यह है कि 0x0000 विंडोज collations में एक अपरिभाषित चरित्र है के कारण है। सभी अपरिभाषित वर्ण तुलना, क्रमबद्ध, और पैटर्न मिलान के दौरान अनदेखा कर रहे हैं। तो 'ए' + char (0) की खोज वास्तव में 'ए' के ​​लिए खोज रही है, और चार (0) के लिए खोज खाली स्ट्रिंग के बराबर है।

तरह से अपरिभाषित चरित्र को संभालने के लिए एक सा भ्रामक है, लेकिन इस तरीका है कि विंडोज उन्हें, सॉर्ट करने के लिए परिभाषित और SQL सर्वर सामान्य Windows API का पालन हो रहा है।

एसक्यूएल collation में, अपरिभाषित चरित्र की कोई धारणा नहीं है। प्रत्येक कोड बिंदु वजन निर्धारित किया जाता है, यही कारण है कि हमें कोई समस्या नहीं दिखाई देती है।

2

इस प्रयास करें, यह SQL सर्वर 2005 पर मेरे लिए काम करता है:

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

कोई गंदा collations के विचार करने के लिए :-)