यदि आप NVARCHAR
. के साथ काम कर रहे हैं / NCHAR
डेटा (जिसे UTF-16 Little Endian . के रूप में संग्रहीत किया जाता है) ), तो आप Unicode
. का उपयोग करेंगे एन्कोडिंग, नहीं BigEndianUnicode
. .NET में, UTF-16 को Unicode
. कहा जाता है जबकि अन्य यूनिकोड एन्कोडिंग को उनके वास्तविक नामों से संदर्भित किया जाता है:UTF7, UTF8, और UTF32। इसलिए, Unicode
अपने आप में Little Endian
है BigEndianUnicode
. के विपरीत . अद्यतन करें: कृपया UCS-2 और पूरक वर्णों से संबंधित अनुभाग को अंत में देखें।
डेटाबेस की तरफ:
SELECT HASHBYTES('MD5', N'è') AS [HashBytesNVARCHAR]
-- FAC02CD988801F0495D35611223782CF
.NET की तरफ:
System.Text.Encoding.ASCII.GetBytes("è")
// D1457B72C3FB323A2671125AEF3EAB5D
System.Text.Encoding.UTF7.GetBytes("è")
// F63A0999FE759C5054613DDE20346193
System.Text.Encoding.UTF8.GetBytes("è")
// 0A35E149DBBB2D10D744BF675C7744B1
System.Text.Encoding.UTF32.GetBytes("è")
// 86D29922AC56CF022B639187828137F8
System.Text.Encoding.BigEndianUnicode.GetBytes("è")
// 407256AC97E4C5AEBCA825DEB3D2E89C
System.Text.Encoding.Unicode.GetBytes("è") // this one matches HASHBYTES('MD5', N'è')
// FAC02CD988801F0495D35611223782CF
हालाँकि, यह प्रश्न VARCHAR
. से संबंधित है / CHAR
डेटा, जो ASCII है, और इसलिए चीजें थोड़ी अधिक जटिल हैं।
डेटाबेस की तरफ:
SELECT HASHBYTES('MD5', 'è') AS [HashBytesVARCHAR]
-- 785D512BE4316D578E6650613B45E934
हम ऊपर .NET पक्ष पहले ही देख चुके हैं। उन हैश किए गए मानों से दो प्रश्न होने चाहिए:
- क्यों नहीं कोई उनमें से
HASHBYTES
. से मेल खाते हैं मूल्य? - @Eric J.'s answer में जुड़ा "sqlteam.com" लेख क्यों दिखाता है कि उनमें से तीन (
ASCII
,UTF7
, औरUTF8
) सभीHASHBYTES
. से मेल खाते हैं मूल्य?
एक उत्तर है जिसमें दोनों प्रश्न शामिल हैं:कोड पृष्ठ। "एसक्यूएलटीम" आलेख में किए गए परीक्षण में "सुरक्षित" ASCII वर्णों का उपयोग किया गया है जो 0 - 127 श्रेणी (इंट/दशमलव मान के संदर्भ में) में हैं जो कोड पेजों के बीच भिन्न नहीं होते हैं। लेकिन 128 - 255 रेंज - जहां हम "è" वर्ण पाते हैं - विस्तारित . है सेट जो कोड पेज के अनुसार अलग-अलग होता है (जो समझ में आता है क्योंकि कोड पेज होने का यही कारण है)।
अब कोशिश करें:
SELECT HASHBYTES('MD5', 'è' COLLATE SQL_Latin1_General_CP1255_CI_AS) AS [HashBytes]
-- D1457B72C3FB323A2671125AEF3EAB5D
यह ASCII
. से मेल खाता है हैशेड मान (और फिर से, क्योंकि "sqlteam" लेख / परीक्षण में 0 - 127 श्रेणी में मानों का उपयोग किया गया था, उन्होंने COLLATE
का उपयोग करते समय कोई परिवर्तन नहीं देखा। ) बढ़िया, अब हमें अंततः VARCHAR
. से मिलान करने का एक तरीका मिल गया है / CHAR
जानकारी। सब ठीक?
असल में ऐसा नहीं है। आइए एक नज़र डालते हैं कि हम वास्तव में क्या हैशिंग कर रहे थे:
SELECT 'è' AS [TheChar],
ASCII('è') AS [TheASCIIvalue],
'è' COLLATE SQL_Latin1_General_CP1255_CI_AS AS [CharCP1255],
ASCII('è' COLLATE SQL_Latin1_General_CP1255_CI_AS) AS [TheASCIIvalueCP1255];
रिटर्न:
TheChar TheASCIIvalue CharCP1255 TheASCIIvalueCP1255
è 232 ? 63
एक ?
? बस सत्यापित करने के लिए, चलाएं:
SELECT CHAR(63) AS [WhatIs63?];
-- ?
आह, इसलिए कोड पेज 1255 में è
. नहीं है चरित्र, तो यह हर किसी के पसंदीदा के रूप में अनुवादित हो जाता है ?
. लेकिन फिर ASCII एन्कोडिंग का उपयोग करते समय .NET में MD5 हैशेड मान से मिलान क्यों हुआ? क्या ऐसा हो सकता है कि हम वास्तव में è
. के हैशेड मान से मेल नहीं खा रहे थे , लेकिन इसके बजाय ?
. के हैशेड मान से मेल खा रहे थे :
SELECT HASHBYTES('MD5', '?') AS [HashBytesVARCHAR]
-- 0xD1457B72C3FB323A2671125AEF3EAB5D
हां। सही ASCII वर्ण सेट बस है पहले 128 वर्ण (मान 0 - 127)। और जैसा कि हमने अभी देखा, è
232 है। तो, ASCII
. का उपयोग करके .NET में एन्कोडिंग उतना उपयोगी नहीं है। न ही COLLATE
. का उपयोग कर रहा था टी-एसक्यूएल की तरफ।
क्या .NET पक्ष पर बेहतर एन्कोडिंग प्राप्त करना संभव है? हाँ, Encoding.GetEncoding(Int32) का उपयोग करके, जो कोड पेज को निर्दिष्ट करने की अनुमति देता है। उपयोग करने के लिए कोड पृष्ठ को निम्न क्वेरी का उपयोग करके खोजा जा सकता है (sys.columns
. का उपयोग करें) एक शाब्दिक या चर के बजाय एक स्तंभ के साथ काम करते समय):
SELECT sd.[collation_name],
COLLATIONPROPERTY(sd.[collation_name], 'CodePage') AS [CodePage]
FROM sys.databases sd
WHERE sd.[name] = DB_NAME(); -- replace function with N'{db_name}' if not running in the DB
उपरोक्त क्वेरी रिटर्न (मेरे लिए):
Latin1_General_100_CI_AS_SC 1252
तो, आइए कोड पेज 1252 आज़माएँ:
System.Text.Encoding.GetEncoding(1252).GetBytes("è") // Matches HASHBYTES('MD5', 'è')
// 785D512BE4316D578E6650613B45E934
वू हू! हमारे पास VARCHAR
. के लिए एक मैच है डेटा जो हमारे डिफ़ॉल्ट SQL सर्वर संयोजन का उपयोग करता है :)। बेशक, यदि डेटा किसी डेटाबेस या फ़ील्ड सेट से किसी भिन्न संयोजन में आ रहा है, तो GetEncoding(1252)
हो सकता है काम नहीं करता है और आपको ऊपर दिखाई गई क्वेरी का उपयोग करके वास्तविक मिलान कोड पृष्ठ ढूंढना होगा (एक कोड पृष्ठ कई कॉलेशन में उपयोग किया जाता है, इसलिए एक अलग कोलेशन जरूरी नहीं है एक अलग कोड पेज का संकेत दें)।
यह देखने के लिए कि संभावित कोड पृष्ठ मान क्या हैं, और वे किस संस्कृति/स्थान से संबंधित हैं, कृपया यहां कोड पृष्ठों की सूची देखें (सूची "टिप्पणी" अनुभाग में है)।
जो वास्तव में NVARCHAR
में संग्रहीत है, उससे संबंधित अतिरिक्त जानकारी / NCHAR
फ़ील्ड:
कोई भी UTF-16 कैरेक्टर (2 या 4 बाइट्स) स्टोर किया जा सकता है, हालांकि बिल्ट-इन फ़ंक्शंस का डिफ़ॉल्ट व्यवहार मानता है कि सभी कैरेक्टर UCS-2 (प्रत्येक 2 बाइट्स) हैं, जो UTF-16 का सबसेट है। SQL सर्वर 2012 से शुरू होकर, विंडोज कॉलेशन के एक सेट तक पहुंचना संभव है जो पूरक वर्णों के रूप में ज्ञात 4 बाइट वर्णों का समर्थन करता है। _SC
in में समाप्त होने वाले इन विंडोज़ कॉलेशनों में से किसी एक का उपयोग करना , या तो एक कॉलम के लिए या सीधे एक क्वेरी में निर्दिष्ट, बिल्ट-इन फ़ंक्शंस को 4 बाइट वर्णों को ठीक से संभालने की अनुमति देगा।
-- The database's collation is set to: SQL_Latin1_General_CP1_CI_AS
SELECT N'𨝫' AS [SupplementaryCharacter],
LEN(N'𨝫') AS [LEN],
DATALENGTH(N'𨝫') AS [DATALENGTH],
UNICODE(N'𨝫') AS [UNICODE],
LEFT(N'𨝫', 1) AS [LEFT],
HASHBYTES('MD5', N'𨝫') AS [HASHBYTES];
SELECT N'𨝫' AS [SupplementaryCharacter],
LEN(N'𨝫' COLLATE Latin1_General_100_CI_AS_SC) AS [LEN],
DATALENGTH(N'𨝫' COLLATE Latin1_General_100_CI_AS_SC) AS [DATALENGTH],
UNICODE(N'𨝫' COLLATE Latin1_General_100_CI_AS_SC) AS [UNICODE],
LEFT(N'𨝫' COLLATE Latin1_General_100_CI_AS_SC, 1) AS [LEFT],
HASHBYTES('MD5', N'𨝫' COLLATE Latin1_General_100_CI_AS_SC) AS [HASHBYTES];
रिटर्न:
SupplementaryChar LEN DATALENGTH UNICODE LEFT HASHBYTES
𨝫 2 4 55393 � 0x7A04F43DA81E3150F539C6B99F4B8FA9
𨝫 1 4 165739 𨝫 0x7A04F43DA81E3150F539C6B99F4B8FA9
जैसा कि आप देख सकते हैं, न तो DATALENGTH
न ही HASHBYTES
प्रभावित कर रहे हैं। अधिक जानकारी के लिए, कृपया कोलेशन और यूनिकोड समर्थन के लिए MSDN पृष्ठ देखें (विशेषकर "सप्लीमेंट्री कैरेक्टर" अनुभाग)।