SQL सर्वर 2008 खाली स्ट्रिंग बनाम अंतरिक्ष


83

मैं आज सुबह कुछ अजीब सा था और मैंने सोचा कि मैं इसे कमेंट्री के लिए प्रस्तुत करूंगा।

क्या कोई समझा सकता है कि निम्न SQL क्वेरी SQL 2008 के विरुद्ध चलने पर 'बराबर' क्यों प्रिंट होती है। db संगतता स्तर 100 पर सेट है।

if '' = ' '
    print 'equal'
else
    print 'not equal'

और यह रिटर्न 0:

select (LEN(' '))

यह अंतरिक्ष को ऑटो ट्रिम करता हुआ प्रतीत होता है। मुझे नहीं पता कि यह SQL सर्वर के पिछले संस्करणों में मामला था, और मेरे पास अब इसे परीक्षण करने के लिए कोई भी आसपास नहीं है।

मैं इसमें भाग गया क्योंकि एक उत्पादन क्वेरी गलत परिणाम दे रही थी। मुझे यह व्यवहार कहीं भी प्रलेखित नहीं मिला।

क्या इस पर किसी के पास कोई सूचना है?


2
SQL 2005: सेलेक्ट लेन ('') रिटर्न 0
मेयो

1
यह Sql Server 2000 पर भी ऐसा ही करता है।
पियरे-एलेन विगेंट सिप

1
यह एक आकर्षक प्रश्न है। ऐसा लगता है कि चाहे वे मेल खाते हों या न हों, दोनों में से कितने रिक्त स्थान पर समान रूप से लौटते हैं। अधिक प्रयोग के बाद मैंने देखा कि यह तुलना से पहले समानता ऑपरेटर के दोनों तरफ प्रभावी रूप से आरटीआरआईएम कर रहा है। ऐसा लगता है कि आपको LEN फ़ंक्शन पर एक उत्तर मिला है, लेकिन मैं वास्तव में "varchars और समानता TS TSQ में कांटेदार हैं" की तुलना में आपके प्रश्न के समानता भाग के लिए अधिक गहन उत्तर में रुचि रखता हूं।
JohnFx

ओरेकल भी ऐसा करता है, मेरा मानना ​​है।
क्विलब्रेकर

सामान्य तौर पर मुझे पता चलता है कि खाली स्ट्रिंग को स्टोर करना एक बुरा विचार है और यह एक कारण है। मैं नल के उपयोग को पसंद करता हूं और कई समस्याओं का पता लगाता हूं, जब लोग रिक्त स्ट्रिंग जैसे मूल्य या सामान्य सीमा से बाहर डेटा तरीके से शून्य जानकारी बनाने की कोशिश करते हैं।
HLGEM

जवाबों:


89

varcharTSQL में s और समानता कांटेदार हैं। LENसमारोह का कहना है:

दिए गए स्ट्रिंग अभिव्यक्ति के बाइट्स की संख्या के बजाय, वर्णों की संख्या देता है, अनुगामी रिक्त स्थान को छोड़कर

आपको DATALENGTHएक सच पाने के लिए उपयोग करने की आवश्यकता हैbyte प्रश्न में डेटा की गणना । यदि आपके पास यूनिकोड डेटा है, तो ध्यान दें कि इस स्थिति में आपको मिलने वाला मूल्य पाठ की लंबाई के समान नहीं होगा।

print(DATALENGTH(' ')) --1
print(LEN(' '))        --0

जब अभिव्यक्ति की समानता की बात आती है, तो दो तारों की तुलना समानता के लिए की जाती है:

  • शार्ट स्ट्रिंग प्राप्त करें
  • पैड खाली के साथलंबाई के बराबर होने तक
  • दोनों की तुलना करें

यह मध्य चरण है जो अप्रत्याशित परिणाम पैदा कर रहा है - उस कदम के बाद, आप व्हाट्सएप के खिलाफ व्हाट्सएप की तुलना प्रभावी ढंग से कर रहे हैं - इसलिए उन्हें बराबर देखा जाता है।

LIKE="रिक्त" स्थिति की तुलना में बेहतर व्यवहार करता है क्योंकि यह उस पैटर्न पर खाली-पैडिंग नहीं करता है जिसे आप मैच करने की कोशिश कर रहे थे:

if '' = ' '
print 'eq'
else
print 'ne'

eqजबकि दे देंगे :

if '' LIKE ' '
print 'eq'
else
print 'ne'

दे देंगे ne

LIKEहालांकि इसके साथ सावधान : यह सममित नहीं है: यह अनुरेखण व्हाट्सएप को पैटर्न (आरएचएस) में महत्वपूर्ण मानता है लेकिन मैच की अभिव्यक्ति (एलएचएस) नहीं। निम्नलिखित यहाँ से लिया गया है :

declare @Space nvarchar(10)
declare @Space2 nvarchar(10)

set @Space = ''
set @Space2 = ' '

if @Space like @Space2
print '@Space Like @Space2'
else
print '@Space Not Like @Space2'

if @Space2 like @Space
print '@Space2 Like @Space'
else
print '@Space2 Not Like @Space'

@Space Not Like @Space2
@Space2 Like @Space

1
अच्छा उत्तर। मैंने देखा नहीं है कि LEN प्रलेखन में। हालांकि यह LEN तक सीमित नहीं है। राइट और LEFT फ़ंक्शन समान व्यवहार प्रदर्शित करता है, लेकिन वहां यह प्रलेखित नहीं है। यह एक अंतरिक्ष के साथ शाब्दिक लगता है जो इस मुद्दे का कारण बनता है। मैंने देखा कि यह भी समान रिटर्न देता है: यदि '= = स्पेस (1) प्रिंट' बराबर 'और प्रिंट नहीं' बराबर 'मैं वास्तव में वास्तविक लंबाई प्राप्त करने में दिलचस्पी नहीं रखता हूं, तो मैं बस उलझन में था कि जब मैं अंतरिक्ष में तलाश कर रहा था तो मैं क्यों? एक स्तंभ, सभी स्तंभ जो खाली तार थे, वापस आ गए।
झेल

इसके अलावा, LIKE स्टेटमेंट के बारे में अच्छी जानकारी। मुझे लगता है कि कहानी की नैतिकता को अपने आप को उस स्थिति में नहीं लाने की कोशिश की जाती है जहां आपको एक स्थान और एक खाली स्ट्रिंग की तुलना करने की आवश्यकता होती है।
जले

2
किसी रिक्त स्ट्रिंग के लिए स्थान की तुलना करने से समस्या बड़ी है। किसी भी दो स्ट्रिंग्स की तुलना करना जो अलग-अलग स्थानों में समाप्त होते हैं, समान व्यवहार प्रदर्शित करते हैं।
JohnFx

3
@butterchicken: इतनी देर की पोस्ट के लिए क्षमा करें, मैंने अभी यह प्रश्न देखा है, लेकिन जब मैंने इसे (अंतिम एक) अपने sql-server-2008 r2I get, पर चलाया @Space Not Like @Space2 @Space2 Not Like @Space । कोई विचार क्यों?
Razort4x

1
SQL सर्वर 2012 और SQL सर्वर 2014 पर पुष्टि की, परिणाम है@Space Not Like @Space2 @Space2 Not Like @Space
बस

19

= ऑपरेटर टी-एसक्यूएल इतना "बराबर" नहीं है क्योंकि यह "समान शब्द / वाक्यांश हैं, जो अभिव्यक्ति के संदर्भ के टकराव के अनुसार," और LEN है "शब्द / वाक्यांश में वर्णों की संख्या।" कोई भी टकराव शब्द / वाक्यांश के पूर्व भाग के रूप में खाली कंबल का इलाज नहीं करता है (हालांकि वे उस स्ट्रिंग के भाग के रूप में अग्रणी रिक्त को मानते हैं)।

यदि आपको 'इस' को 'इस' से अलग करने की आवश्यकता है, तो आपको "समान शब्द या वाक्यांश" ऑपरेटर का उपयोग नहीं करना चाहिए क्योंकि 'यह' और 'यह' एक ही शब्द हैं।

रास्ते में योगदान देना = कार्य यह विचार है कि स्ट्रिंग-इक्वैलिटी ऑपरेटर को अपने तर्कों की सामग्री पर और अभिव्यक्ति के टकराव के संदर्भ पर निर्भर होना चाहिए, लेकिन यह दोनों प्रकार के तर्कों पर निर्भर नहीं होना चाहिए, यदि वे दोनों स्ट्रिंग प्रकार हैं ।

"ये एक ही शब्द हैं" की प्राकृतिक भाषा अवधारणा आमतौर पर = जैसे गणितीय ऑपरेटर द्वारा कब्जा करने में सक्षम होने के लिए पर्याप्त सटीक नहीं है, और प्राकृतिक भाषा में स्ट्रिंग प्रकार की कोई अवधारणा नहीं है। प्रसंग (यानी, टकराव) मायने रखता है (और प्राकृतिक भाषा में मौजूद है) और कहानी का हिस्सा है, और अतिरिक्त गुण (कुछ जो विचित्र लगते हैं) = की परिभाषा का हिस्सा हैं ताकि इसे अप्राकृतिक दुनिया में अच्छी तरह से परिभाषित किया जा सके डेटा।

प्रकार के मुद्दे पर, आप शब्दों को तब बदलना नहीं चाहेंगे जब वे विभिन्न स्ट्रिंग प्रकारों में संग्रहीत हों। उदाहरण के लिए, प्रकार VARCHAR (10), CHAR (10), और CHAR (3) सभी शब्द 'कैट' का प्रतिनिधित्व कर सकते हैं, और? = 'कैट' को हमें यह तय करने देना चाहिए कि क्या इनमें से किसी भी प्रकार का मान 'कैट' शब्द के साथ है (टकराव के द्वारा निर्धारित मामलों और उच्चारण के मुद्दों के साथ)।

JohnFx की टिप्पणी का जवाब:

चार और चर डेटा का उपयोग करना देखेंऑनलाइन पुस्तकों में । उस पृष्ठ से उद्धरण, मेरा जोर:

प्रत्येक चार्ट और varchar डेटा मान में एक टकराव होता है। कोलाज प्रत्येक चरित्र, तुलना नियमों का प्रतिनिधित्व करने के लिए उपयोग किए जाने वाले बिट पैटर्न जैसी विशेषताओं को परिभाषित करते हैं , और मामले या उच्चारण के प्रति संवेदनशीलता।

मैं मानता हूं कि इसे खोजना आसान हो सकता है, लेकिन यह प्रलेखित है।

वर्थ नोटिंग भी, SQL का शब्दार्थ है, जहाँ = का वास्तविक दुनिया के आंकड़ों और तुलना के संदर्भ (कंप्यूटर पर संग्रहीत बिट्स के बारे में कुछ के विपरीत) के साथ लंबे समय तक एसक्यूएल का हिस्सा रहा है। आरडीबीएमएस और एसक्यूएल का आधार वास्तविक दुनिया के डेटा का वफादार प्रतिनिधित्व है, इसलिए समान विचारों (जैसे कि संस्कृतिइन्फो) से पहले कई वर्षों के टकराव के लिए इसका समर्थन अल्गोल जैसी भाषाओं के दायरे में प्रवेश किया। उन भाषाओं का आधार (कम से कम बहुत हाल तक) इंजीनियरिंग में समस्या-समाधान था, न कि व्यावसायिक डेटा का प्रबंधन। (हाल ही में, गैर-इंजीनियरिंग अनुप्रयोगों में समान भाषाओं का उपयोग खोज की तरह कुछ अयोग्य बना रहा है, लेकिन जावा, सी #, और इसी तरह अभी भी अपनी गैर-व्यावसायिक जड़ों से जूझ रहे हैं।)

मेरी राय में, "अधिकांश प्रोग्रामिंग भाषाओं" से अलग होने के लिए SQL की आलोचना करना उचित नहीं है। SQL को व्यवसाय डेटा मॉडलिंग के लिए एक फ्रेमवर्क का समर्थन करने के लिए डिज़ाइन किया गया था जो इंजीनियरिंग से बहुत अलग है, इसलिए भाषा अलग है (और अपने लक्ष्य के लिए बेहतर है)।

हेक, जब एसक्यूएल पहली बार निर्दिष्ट किया गया था, कुछ भाषाओं में कोई अंतर्निहित स्ट्रिंग प्रकार नहीं था। और कुछ भाषाओं में अभी भी, स्ट्रिंग्स के बीच बराबर ऑपरेटर चरित्र डेटा की तुलना बिल्कुल नहीं करता है, लेकिन संदर्भों की तुलना करता है! यह मुझे आश्चर्यचकित नहीं करेगा यदि एक या दो दशक में, यह विचार == संस्कृति पर निर्भर है कि आदर्श बन जाता है।


BOL इस प्रकार = ऑपरेटर का वर्णन करता है: "दो अभिव्यक्तियों (एक तुलना ऑपरेटर) की समानता की तुलना करता है।" व्यवहार सही है या नहीं, आपको यह स्वीकार करना होगा कि अधिकांश प्रोग्रामिंग भाषाओं में इस ऑपरेटर के उपयोग के मामले में यह बेहद भ्रामक और गैर-मानक है। एमएस को कम से कम इस व्यवहार के बारे में प्रलेखन के लिए एक चेतावनी जोड़नी चाहिए।
JohnFx

@JohnFx: मेरे जवाब में टिप्पणी के लिए मेरी बहुत लंबी-चौड़ी प्रतिक्रिया देखें।
स्टीव कैस

9

मुझे यह ब्लॉग लेख मिला जो व्यवहार का वर्णन करता है और बताता है कि क्यों।

SQL मानक के लिए आवश्यक है कि स्ट्रिंग तुलना, प्रभावी रूप से, अंतरिक्ष वर्णों के साथ छोटी स्ट्रिंग को पैड करे। यह आश्चर्यजनक परिणाम की ओर जाता है कि एन '' = एन '' (खाली स्ट्रिंग एक या अधिक अंतरिक्ष वर्णों के स्ट्रिंग के बराबर होती है) और आम तौर पर कोई भी स्ट्रिंग किसी अन्य स्ट्रिंग के बराबर होती है यदि वे केवल अनुगामी रिक्त स्थान से भिन्न होती हैं। यह कुछ संदर्भों में एक समस्या हो सकती है।

अधिक जानकारी MSKB316626 में भी उपलब्ध है


धन्यवाद। मुझे आश्चर्य है कि यह मानक में है। मुझे यकीन है कि मैं इससे बेहतर कारण होने के बावजूद किसी को अधिक चालाक समझ सकता हूं।
१५:०५ पर jhale

@ जॉन: क्या आपको अपनी टिप्पणी में ≠ (बराबरी नहीं) लिखने का मतलब है?
स्टीव कैस

मूल उद्धरण में एक त्रुटि थी जिसे मैंने सीधे कॉपी किया था। मैंने यह दर्शाने के लिए बोली को अद्यतन किया कि मूल लेखक का क्या मतलब है।
JohnFx

5

कुछ समय पहले भी इसी तरह का सवाल था, जहां मैंने एक समान समस्या पर ध्यान दिया

इसके बजाय LEN(' '), उपयोग DATALENGTH(' ')- जो आपको सही मूल्य देता है।

समाधानों का उपयोग एक LIKEक्लॉज का उपयोग करना था जैसा कि मेरे उत्तर में बताया गया है, और / या WHEREक्लॉज़ में दूसरी स्थिति को जाँचने के लिए शामिल किया गया हैDATALENGTH भी शामिल है।

उस प्रश्न और लिंक को वहां पढ़ें।


3

मान को शाब्दिक स्थान से तुलना करने के लिए, आप इस तकनीक का उपयोग LIKE स्टेटमेंट के विकल्प के रूप में भी कर सकते हैं:

IF ASCII('') = 32 PRINT 'equal' ELSE PRINT 'not equal'

0

Sql सर्वर पर फ़ील्ड char / varchar के साथ चयन पर अलग रिकॉर्ड कैसे करें: उदाहरण:

declare @mayvar as varchar(10)

set @mayvar = 'data '

select mykey, myfield from mytable where myfield = @mayvar

अपेक्षित होना

mykey (int) | myfield (varchar10)

1 | 'डेटा '

प्राप्त

मायकी | मेरा क्षेत्र

1 | 'डेटा' 2 | 'डेटा '

भले ही मैं लिखूं select mykey, myfield from mytable where myfield = 'data' (अंतिम रिक्त के बिना) मुझे वही परिणाम मिलते हैं।

मैंने कैसे हल किया? इस मोड में:

select mykey, myfield
from mytable
where myfield = @mayvar 
and DATALENGTH(isnull(myfield,'')) = DATALENGTH(@mayvar)

और अगर myfield पर कोई इंडेक्स है, तो इसका उपयोग प्रत्येक मामले में किया जाएगा।

मुझे उम्मीद है कि यह मददगार होगा।


0

दूसरा तरीका यह है कि इसे उस स्थिति में वापस रखा जाए, जिसमें स्थान का मूल्य हो। उदाहरण के लिए: _ जैसे अक्षर वाले स्थान को बदलें

if REPLACE('hello',' ','_') = REPLACE('hello ',' ','_')
    print 'equal'
else
    print 'not equal'

रिटर्न: नहीं के बराबर

आदर्श नहीं है, और शायद धीमा है, लेकिन जल्दी से जरूरत पड़ने पर एक और त्वरित तरीका है।


0

कभी-कभी किसी को किसी अन्य वर्ण के साथ या बिना डेटा के रिक्त स्थान से निपटना पड़ता है, भले ही नल का उपयोग करने का विचार बेहतर है - लेकिन हमेशा उपयोगी नहीं है। मैंने वर्णित स्थिति में भाग लिया और इसे इस तरह हल किया:

... where ('>' + @space + '<') <> ('>' + @space2 + '<')

बेशक आप बड़ी मात्रा में डेटा के लिए ऐसा नहीं करेंगे, लेकिन यह कुछ सौ लाइनों के लिए त्वरित और आसान काम करता है ...


1
प्रश्न यह था कि एसक्यूएल सर्वर ने जैसा व्यवहार किया था, वैसा व्यवहार सामान्य रूप से कैसे किया जाए। झेल शायद अपने प्रोग्राम कोड को संशोधित नहीं करेंगे, केवल अपने सर्वर कॉन्फ़िगरेशन को।
लुत्ज प्रेचल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.