LEN फ़ंक्शन SQL सर्वर में अनुगामी रिक्त स्थान शामिल नहीं करता है


109

मेरे पास SQL ​​Server 2005 में निम्नलिखित परीक्षण तालिका है:

CREATE TABLE [dbo].[TestTable]
(
 [ID] [int] NOT NULL,
 [TestField] [varchar](100) NOT NULL
) 

इसके साथ आबादी:

INSERT INTO TestTable (ID, TestField) VALUES (1, 'A value');   -- Len = 7
INSERT INTO TestTable (ID, TestField) VALUES (2, 'Another value      '); -- Len = 13 + 6 spaces

जब मैं SQL सर्वर LEN () फ़ंक्शन के साथ TestField की लंबाई खोजने की कोशिश करता हूं तो यह अनुगामी रिक्त स्थान की गणना नहीं करता है - उदाहरण:

-- Note: Also results the grid view of TestField do not show trailing spaces (SQL Server 2005).
SELECT 
 ID, 
 TestField, 
 LEN(TestField) As LenOfTestField, -- Does not include trailing spaces
FROM 
 TestTable

मैं लंबाई परिणाम में अनुगामी रिक्त स्थान कैसे शामिल करूं?


1
मुझे लगता है कि Microsoft का असली समाधान उनके टूटे हुए सॉफ़्टवेयर को ठीक करने के लिए हो सकता है। यहाँ वोट करें: feedback.azure.com/forums/908035-sql-server/suggestions/…
QA कलेक्टिव

जवाबों:


125

यह MSDN में Microsoft द्वारा http://msdn.microsoft.com/en-us/library/ms190329(SQL.90).aspx पर स्पष्ट रूप से प्रलेखित है , जो बताता है कि LEN "निर्दिष्ट स्ट्रिंग अभिव्यक्ति के वर्णों की संख्या देता है, सिवाय पीछे चल रहा है "। हालांकि, यह याद रखना आसान है कि अगर आप सावधान नहीं हैं।

इसके बजाय आपको DATALENGTH फ़ंक्शन का उपयोग करने की आवश्यकता है - http://msdn.microsoft.com/en-us/library/ms173486(SQL.90).aspx - जो "बाइट्स की संख्या को किसी भी अभिव्यक्ति का प्रतिनिधित्व करने के लिए वापस लौटाता है" देखें।

उदाहरण:

SELECT 
    ID, 
    TestField, 
    LEN(TestField) As LenOfTestField,           -- Does not include trailing spaces
    DATALENGTH(TestField) As DataLengthOfTestField      -- Shows the true length of data, including trailing spaces.
FROM 
    TestTable

52
ध्यान दें: क्योंकि DATALENGTHपरिणाम का परीक्षण एक विस्तृत वर्ण प्रकार (यूनिकोड, nchar, nvarchar या ntext) है, तो आपको परिणाम 2 से विभाजित करने की आवश्यकता होगी, क्योंकि परिणाम बाइट्स में है , वर्ण नहीं ।
devstuff

7
इसके अलावा varcharआदि के लिए यह निर्भरता हो सकती है और 2 से एक सीधे आगे विभाजन भी विश्वसनीय नहीं है। यहां उदाहरण
मार्टिन स्मिथ

18
मैं उपयोग करूंगा LEN(REPLACE(expr, ' ', '_'))। इसके साथ काम करना चाहिए varcharऔर nvarcharविशेष यूनिकोड नियंत्रण वर्ण वाले तार।
ओलिवियर जैकोट-डेसकोम्बर्स

6
-1, DATALENGTH()वर्णों को गिनने का एक वैकल्पिक तरीका नहीं माना जाना चाहिए क्योंकि यह वर्णों के बजाय बाइट्स की गणना करता है और जब यह उसी स्ट्रिंग में VARCHAR/ का प्रतिनिधित्व करता है तो मायने रखता है NVARCHAR
बिंकी जू

5
SQL सर्वर 2012 से शुरू, संस्करण 100 कोलाज के साथ यूनिकोड कॉलम अब सरोगेट जोड़े का समर्थन करता है। इसका मतलब है कि एक एकल वर्ण अधिकतम 4 बाइट्स का उपयोग कर सकता है, जिससे विभाजन दो चाल से विफल हो जाता है। एमएसडीएन देखें ।
Frédéric

85

आप इस ट्रिक का उपयोग कर सकते हैं:

LEN (Str + 'x') - 1


15
क्या आप बेहतर विकल्पों के साथ हमें बता सकते हैं, कृपया? Datalength सुनिश्चित नहीं है।
सर्ग

15
मैं दृढ़ता से असहमत हूं कि असंगत तरीके का उपयोग करना (किसी मामले में आप इसके परिणाम को 2 से विभाजित करते हैं और कभी-कभी नहीं) एक बेहतर विकल्प है। हो सकता है कि मेरी पद्धति के साथ शून्य प्रदर्शन हिट के पास है।
सर्ग

5
@usr सर्ज का तरीका सबसे अच्छा है, IMHO। सरल और सुरुचिपूर्ण। DATALENGTH जटिल है: सिंगल / डबल बाइट प्रकार पर निर्भर, कॉलेशन / भाषा पर निर्भर, आदि
श्री टीए

10
यह अब तक का सबसे अच्छा, सुरुचिपूर्ण समाधान है। मुझे वास्तव में परवाह नहीं है अगर यह हैक की तरह है या नहीं (कोडिंग भावनाओं के बारे में नहीं है), मैं वास्तव में इस तथ्य के बारे में परवाह करता हूं कि इस समाधान का कोई दुष्प्रभाव नहीं है। मैं डेटा प्रकार varchar / nvarchar को बदल सकता हूं और यह अभी भी काम करता है। बहुत बढ़िया।
माइक केसिनकोव

5
इस दुष्प्रभाव के कारण कैविएट है। यदि आप प्रकार nvarchar (4000) के एक चर के साथ काम कर रहे हैं, और आपके चर में एक 4000 वर्ण स्ट्रिंग है, तो जोड़ा गया वर्ण अनदेखा किया जाएगा, और आपको गलत परिणाम मिलेगा (SQL की लेन जो अनुगामी रिक्त स्थान को अनदेखा करती है, कम 1 आप घटाते हैं)।
हैचेट -

17

मैं इस विधि का उपयोग करता हूं:

LEN(REPLACE(TestField, ' ', '.'))

मैं इसे DATALENGTH पर पसंद करता हूं क्योंकि यह अलग-अलग डेटा प्रकारों के साथ काम करता है, और मैं इसे अंत में एक चरित्र को जोड़ना पसंद करता हूं क्योंकि आपको किनारे के मामले के बारे में चिंता करने की ज़रूरत नहीं है जहां आपका स्ट्रिंग पहले से ही अधिकतम लंबाई पर है।

नोट: मैं एक बहुत बड़े डेटा सेट के खिलाफ उपयोग करने से पहले प्रदर्शन का परीक्षण करूंगा; हालांकि मैं सिर्फ 2M पंक्तियों के खिलाफ यह परीक्षण किया है और यह रेप्लस के बिना LEN की तुलना में कोई धीमी थी ...


14

"मैं लंबाई परिणाम में अनुगामी रिक्त स्थान कैसे शामिल करूं?"

आपको कोई SQL सर्वर एन्हांसमेंट अनुरोध / बग रिपोर्ट दर्ज करने के लिए मिलता है क्योंकि लगभग सभी सूचीबद्ध वर्कअराउंड इस आश्चर्यजनक सरल समस्या के लिए यहां कुछ कमी है या अक्षम हैं। यह अभी भी SQL Server 2012 में सही प्रतीत होता है। ऑटो ट्रिमिंग सुविधा ANSI / ISO SQL-92 से उपजी हो सकती है, लेकिन इसमें कुछ छेद (या उनकी गिनती की कमी) प्रतीत होती है।

कृपया वोट करें "सेटिंग जोड़ें ताकि LEN गिने जा रहे व्हाट्सएप को गिनें":

https://feedback.azure.com/forums/908035-sql-server/suggestions/34673914-add-setting-so-len-counts-trailing-whitespace

सेवानिवृत्त कनेक्ट लिंक: https://connect.microsoft.com/SQLServer/feedback/details/801381


2
datalengthसमाधान भी बदतर है, एसक्यूएल सर्वर 2012 से शुरू होने वाले के बाद से यह अब UTF-16 में किराए की जोड़े का समर्थन करता है करता है, जिसका अर्थ है एक चरित्र 4 बाइट का उपयोग कर सकते है। यह वास्तव में समय है कि वे lenएएनएसआई के अनुपालन के लिए फ़ंक्शन को ठीक करते हैं , या कम से कम अनुगामी रिक्त स्थान सहित चार्ट की गिनती के लिए एक समर्पित फ़ंक्शन प्रदान करते हैं।
Frédéric

1
प्रतिक्रिया लिंक को इसके लिए अधिक उपयोग करने की आवश्यकता है। यह चौंकाने वाला है कि इस समस्या को केवल इंटरनेट के माध्यम से खोजा जा सकता है। मैंने लगभग 2 घंटे बिताए, यह जानने की कोशिश की कि LEN () फ़ंक्शन मेरे डिस्कनेक्ट का कारण होने से पहले ही मैंने अपने कोड में गलती कर दी थी।
टेकोफिलियाक

मैं इससे सहमत हूं, लेकिन एक पैरामीटर को व्हॉट्सएप को ट्रिम करने की अनुमति देनी चाहिए .. क्योंकि यह ईएफ के साथ स्ट्रिंग तुलना को बहुत आसान बनाता है, यह जांचने के लिए कि क्या व्हाट्सएप शामिल नहीं है जब आईक्वेरीबल अभिव्यक्ति का निर्माण होता है।
गंजैई

9

दो शीर्ष मतदान उत्तरों के साथ समस्याएं हैं। अनुशंसा करने वाला उत्तर DATALENGTHप्रोग्रामर त्रुटियों से ग्रस्त है। परिणाम को प्रकारों के DATALENGTHलिए 2 से विभाजित किया जाना चाहिए NVARCHAR, लेकिन VARCHARप्रकारों के लिए नहीं । इसके लिए आवश्यक है कि आपको जिस प्रकार की लंबाई मिल रही है, और यदि वह प्रकार बदलता है, तो आपको अपने द्वारा उपयोग किए जाने वाले स्थानों को परिश्रम से बदलना होगा DATALENGTH

सबसे अपवित्र उत्तर के साथ एक समस्या भी है (जो मैं मानता हूं कि यह करने के लिए मेरा पसंदीदा तरीका था जब तक कि यह समस्या मुझे नहीं हो जाती)। यदि आप जिस चीज की लंबाई प्राप्त कर रहे हैं वह प्रकार की है NVARCHAR(4000), और इसमें वास्तव में 4000 वर्णों की एक स्ट्रिंग शामिल है, तो SQL परिणाम को डाले जाने के बजाय संलग्न चरित्र को अनदेखा करेगा NVARCHAR(MAX)। अंतिम परिणाम एक गलत लंबाई है। यही बात VARCHAR (8000) के साथ भी होगी।

मैंने जो काम पाया है, वह लगभग उतना ही तेज है, जितना पुराना है LEN, LEN(@s + 'x') - 1बड़े तार की तुलना में तेज़ है , और यह अंतर्निहित वर्ण चौड़ाई को नहीं मानता है:

DATALENGTH(@s) / DATALENGTH(LEFT(LEFT(@s, 1) + 'x', 1))

यह डटलट्रोम प्राप्त करता है, और फिर स्ट्रिंग से किसी एकल वर्ण के डटलट्रोम द्वारा विभाजित होता है। 'X' का परिशिष्ट उस मामले को शामिल करता है जहां स्ट्रिंग खाली है (जो उस मामले में शून्य से भाग देगा)। यह काम करता @sहै VARCHARया नहीं NVARCHARLEFTएपेंड करने से पहले 1 वर्ण का करना कुछ समय के लिए होता है जब स्ट्रिंग बड़ी होती है। हालांकि इसके साथ समस्या यह है कि यह सरोगेट जोड़े वाले तारों के साथ सही ढंग से काम नहीं करता है।

उपयोग किए गए उत्तर के लिए एक टिप्पणी में वर्णित एक और तरीका है REPLACE(@s,' ','x')। यह तकनीक सही उत्तर देती है, लेकिन जब स्ट्रिंग बड़ी होती है तो यह अन्य तकनीकों की तुलना में परिमाण को धीमा करने का एक युगल आदेश है।

किसी भी तकनीक का उपयोग करने पर सरोगेट जोड़े द्वारा पेश की गई समस्याओं को देखते हुए DATALENGTH, मुझे लगता है कि सबसे सुरक्षित तरीका है जो सही उत्तर देता है जो मुझे पता है कि निम्नलिखित हैं:

LEN(CONVERT(NVARCHAR(MAX), @s) + 'x') - 1

यह REPLACEतकनीक से तेज है , और लंबे समय तक तार के साथ बहुत तेज है। मूल रूप से यह तकनीक तकनीक है LEN(@s + 'x') - 1, लेकिन किनारे के मामले के लिए सुरक्षा के साथ जहां स्ट्रिंग की लंबाई 4000 (nvarchar) या 8000 (varchar के लिए) है, ताकि उसके लिए भी सही उत्तर दिया जा सके। यह भी सरोगेट जोड़े के साथ तार को सही ढंग से संभालना चाहिए।


1
दुर्भाग्य से, यह जवाब अब SQL Server 2012 में सरोगेट जोड़े वाले स्ट्रिंग्स के लिए काम नहीं करता है। N'x𤭢x' COLLATE Latin1_General_100_CI_AS_SC4 पर अपना ऑपरेशन चला रहा है , जबकि LEN3 देता है।
डगलस

9
@ डगलस - यह उपयोगी जानकारी है। यदि केवल Microsoft ही हमें LEN का एक संस्करण देता है जो अनुगामी स्थानों को अनदेखा नहीं करता है।
हैचेट - सोवेफ्लो

5

आपको यह भी सुनिश्चित करने की आवश्यकता है कि आपका डेटा वास्तव में ट्रेलिंग ब्लैंक के साथ सहेजा गया है। जब ANSI पैडिंग बंद है (गैर-डिफ़ॉल्ट):

चरित्र मानों में अनुगामी रिक्त स्थान को एक वर्चस् स्तंभ में सम्मिलित किया गया है।


3
मुझे लगता है कि आपको ANSI PADDING को बंद नहीं करना चाहिए क्योंकि यह सेटिंग अप्रचलित है। एक गैर-मानक मूल्य पर होने से कई छोटी समस्याएं होती हैं।
यूएसआर

4

LEN डिफ़ॉल्ट रूप से अनुगामी रिक्त स्थान में कटौती करता है, इसलिए मैंने पाया कि जब आप उन्हें मोर्चे पर ले जाते हैं तो यह काम करता है

(LEN (रिवर्स (TestField))

इसलिए अगर आप चाहते तो कह सकते थे

SELECT
t.TestField,
LEN(REVERSE(t.TestField)) AS [Reverse],
LEN(t.TestField) AS [Count]
FROM TestTable t
WHERE LEN(REVERSE(t.TestField)) <> LEN(t.TestField)

बेशक अग्रणी स्थानों के लिए इसका इस्तेमाल न करें।


9
अब यह ट्रेलिंग स्पेस के बजाय प्रमुख स्थानों को ट्रिम करता है । उसी दिन, अलग समस्या :)
उल्टा इंजीनियर

@DaveBoltman मेरा सुझाव शायद अभी भी अधिक जटिल है, लेकिन आप इसके अलावा TRIM'ed लंबाई के खिलाफ तुलना कर सकते हैं।
ब्रायन जे

यह बग को उलट देता है जहां प्रमुख स्थानों को अनुगामी रिक्त स्थान के बजाय गिना नहीं जाता है। निम्न कोड देखें: declare @TestField varchar(10); SET @TestField = ' abc '; -- Length with spaces is 5. select LEN(REVERSE(@TestField)) -- Returns 4 select LEN(@TestField) -- Returns 4
Metalogic

1

यदि आप स्ट्रिंग समंजन को नापसंद करते हैं, तो आपको एक CLR फ़ंक्शन को परिभाषित करना चाहिए जो स्ट्रिंग की लंबाई फ़ील्ड को लौटाता है। मैं LEN('x' + @string + 'x') - 2अपने उत्पादन उपयोग-मामलों में उपयोग करता हूं।


0

यदि आप DATALENGTHn / varchar चिंताओं के कारण नापसंद करते हैं, तो कैसे:

select DATALENGTH(@var)/isnull(nullif(DATALENGTH(left(@var,1)),0),1)

जो बस है

select DATALENGTH(@var)/DATALENGTH(left(@var,1))

विभाजित-शून्य सुरक्षा के साथ लिपटे।

एक चार के DATALENGTH द्वारा विभाजित करके, हम लंबाई को सामान्यीकृत करते हैं।

(बेशक, अभी भी सरोगेट-जोड़े के साथ समस्या अगर यह एक चिंता का विषय है।)


-4

चयन DATALENGTH ('स्ट्रिंग') का उपयोग करें


2
आपने अभी 7 साल पहले से दूसरों के जवाबों को बहाल किया है और प्रदाता कुछ भी नया नहीं करते हैं या यहां तक ​​कि समझाते हैं कि आप क्या जवाब देते हैं या यह उस प्रश्न का उत्तर कैसे देता है।
Jpsh
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.