अंतरिक्ष के साथ एक कॉलम में विशेष वर्ण बदलें


10

मैं एक क्वेरी लिखने की कोशिश कर रहा हूं जो अंतरिक्ष के साथ विशेष वर्णों को बदलता है। नीचे दिए गए कोड से पंक्तियों की पहचान करने में मदद मिलती है। (अल्फा-न्यूमेरिक वर्ण, अल्पविराम और स्थान मान्य है):

SELECT columnA
FROM tableA
WHERE columnA like '%[^a-Z0-9, ]%'

मैं बदले हुए फ़ंक्शन को चुनिंदा विवरण में कैसे एकीकृत कर सकता हूं ताकि परिणाम सेट में अल्फ़ान्यूमेरिक, अल्पविराम और स्थान के अलावा सभी वर्णों को '' (स्थान) द्वारा बदल दिया जाए। यह काम नहीं करेगा:

SELECT replace(columnA,'%[^a-Z0-9, ]%',' ')
FROM tableA
WHERE columnA like '%[^a-Z0-9, ]%'

जवाबों:


11

यदि आपको केवल अमेरिकी अंग्रेजी वर्णमाला के 26 अक्षरों (ऊपरी-मामले और निचले-मामले दोनों संस्करणों) का उपयोग करने की गारंटी दी जाती है, तो निश्चित रूप से, आप का उपयोग करके LIKEऔर / या PATINDEXसाधारण श्रेणी संकेतन से दूर हो सकते हैं [a-z](आप नहीं कर सकते) केस-असंवेदनशील Collation का उपयोग करते समय एक ऊपरी-केस "Z" का उपयोग करने की आवश्यकता होती है)।

लेकिन, यदि आपको VARCHARडेटा के लिए विभिन्न कोड पेज / कोलाज में अभी तक उपलब्ध एन-यूएस वर्णमाला में नहीं पाए गए अक्षर मिल सकते हैं (जैसे Þ= लैटिन राजधानी "थॉर्न" = SELECT CHAR(0xDE)), तो आपको वर्ण वर्ग में उन लोगों को शामिल करने की आवश्यकता हो सकती है [a-z0-9, Þ]:। बेशक, उन अतिरिक्त वर्णों का प्रति-पृष्ठ पृष्ठ के आधार पर क्या होगा।

इसके अलावा, कृपया ध्यान रखें कि Collation type (SQL Server vs Windows) और संवेदनशीलता सेटिंग्स (केस, एक्सेंट, आदि संवेदनशील बनाम असंवेदनशील) दोनों को प्रभावित करेगा कि कौन से वर्ण किसी विशेष श्रेणी में शामिल हैं। उदाहरण के लिए, SQL सर्वर Collations, Windows Collations के रूप में विपरीत क्रम में ऊपरी-केस और निचले-केस अक्षरों को सॉर्ट करता है। मतलब, दोनों प्रकार के Collations के लिए केस-सेंसिटिव Collation मानकर, एक करेगा AaBb...और दूसरा करेगा aAbB...। इसका प्रभाव यह होगा कि उनमें से एक के लिए aसीमा A-Zहोगी, लेकिन दूसरी नहीं। और a-Zबाइनरी कोलेशन में कोई भी वर्ण मेल नहीं करेगा (एक _BINया तो समाप्त होता है _BIN2, लेकिन उपयोग नहीं करता है _BIN) यह देखते हुए कि मूल्य A65 है औरa97 है, इसलिए यह 65 ;-) के माध्यम से 97 की एक अमान्य श्रेणी है। यहाँ पर उदाहरण देने के लिए बहुत अधिक विविधताएँ हैं इसलिए मैं जल्द ही अपने ब्लॉग पर एक विस्तृत विवरण पोस्ट करने की कोशिश करूँगा (और फिर इसे इसके लिंक के साथ अपडेट करूंगा)। हालांकि, यदि आप केवल अमेरिकी अंग्रेजी वर्णों को स्वीकार करने के बारे में सख्त होने जा रहे हैं (भले ही आपको अन्य भाषाओं से मान्य पत्र मिल सकते हैं) तो आपका सबसे अच्छा विकल्प संभवत : निम्नलिखित पैटर्न और Collation का उपयोग करना होगा :

LIKE '%[^A-Za-z0-9, ]%' COLLATE Latin1_General_100_BIN2

अब, यदि आप NVARCHARडेटा का समर्थन कर रहे हैं और विभिन्न भाषाओं के "शब्द" अक्षर प्राप्त कर सकते हैं, तो टी-एसक्यूएल बहुत मदद नहीं करेगा क्योंकि इन चीजों को अलग करने का कोई वास्तविक तरीका नहीं है। इस स्थिति में, आपको एक नियमित अभिव्यक्ति (RegEx) का उपयोग करना चाहिए - विशेष रूप से Replaceविधि / कार्य - और वे केवल SQLCLR के माध्यम से उपलब्ध हैं। निम्नलिखित कई "विशेष" वर्णों को प्रतिस्थापित करने का एक उदाहरण दिखाता है, फिर भी उन सभी को छोड़ देता है जो कम से कम एक भाषा में मान्य पत्र हैं:

DECLARE @Test NVARCHAR(500);
SET @Test = N'this$is%a<>TEST,;to}⌡↕strip╞╟╚══¶out_ç_ƒ▀ special-ij-೫-chars-舛-დ-א-B';
SELECT SQL#.RegEx_Replace4k(@Test, N'[\W\p{Pc}-[,]]', N' ', -1, 1, NULL); 

यह दिखाता है:

this is a  TEST, to   strip      out ç ƒ  special ij ೫ chars 舛 დ א B

RegEx अभिव्यक्ति का अर्थ है:

  • \W= एक RegEx "बच" का अर्थ है "कोई भी गैर- चरित्र चरित्र"
  • \p{Pc}= "विराम चिह्न, कनेक्टर" का एक यूनिकोड "श्रेणी" (यह केवल मैच के लिए आवश्यक है क्योंकि इस "श्रेणी" को विशेष रूप से \Wभागने से बाहर रखा गया है )
  • -[,]= वर्ग घटाव (यह अल्पविराम को "विशेष" के रूप में मिलान से बाहर करने के लिए आवश्यक है क्योंकि वे \Wभागने में शामिल हैं)

आप केवल जारी करके किसी तालिका का अद्यतन कर सकते हैं:

UPDATE tbl
SET    tbl.field = SQL#.RegEx_Replace4k(tbl.field, N'[\W\p{Pc}-[,]]', N' ', -1, 1, NULL)
FROM   tbl
WHERE  SQL#.RegEx_IsMatch4k(tbl.field, N'[\W\p{Pc}-[,]]', 1, NULL) = 1;

कृपया ध्यान दें कि इन उदाहरणों के लिए, मैंने एसक्यूएलआरआर कार्यों के नि: शुल्क संस्करण एसक्यूएल # लाइब्रेरी में उपलब्ध दो कार्यों का उपयोग किया , जो मैंने बनाए (लेकिन फिर से, ये मुफ्त हैं)। यह भी ध्यान दें कि मैंने "4k" संस्करणों का उपयोग NVARCHAR(4000)किया है जो NVARCHAR(MAX)पैरामीटर प्रकारों के बजाय उपयोग करने के कारण तेज हैं । यदि आपका डेटा उपयोग कर रहा है NVARCHAR(MAX), तो बस फ़ंक्शन नामों से "4k" हटा दें।

कृपया यह भी देखें:


5

मुझे यहाँ एक पोस्ट मिली है जो कुछ ऐसा ही करती है

मूल रूप से मैं एक बार में लूप जाने के लिए एक बार में एक "खराब" चरित्र को बदलने के लिए एक पुनरावर्ती CTE का उपयोग कर रहा हूं। मैं STUFF का उपयोग स्ट्रिप 1 कैरेक्टर के लिए कर रहा हूं (हालाँकि आप इसे स्पेस के साथ बदलने के लिए इस्तेमाल कर सकते हैं) और PATINDEX मैं उस कैरेक्टर की लोकेशन ढूंढना चाहता हूं जिसे मैं हटाना चाहता हूं। आप इसे थोड़ा संशोधित कर सकते हैं कि आप क्या देख रहे हैं। हालाँकि यह "अच्छी" सूची बनाता है, यह वास्तव में मौजूदा सूची को अपडेट नहीं करता है।

DECLARE @Pattern varchar(50) = '%[^A-Za-z0-9, ]%';

WITH FixBadChars AS (SELECT StringToFix, StringToFix AS FixedString, 1 AS MyCounter, Id
                FROM BadStringList
                UNION ALL
                SELECT StringToFix, Stuff(FixedString, PatIndex(@Pattern, 
                    FixedString COLLATE Latin1_General_BIN2), 1, ' ') AS FixedString, 
                    MyCounter + 1, Id
                FROM FixBadChars
                WHERE FixedString COLLATE Latin1_General_BIN2 LIKE @Pattern)
SELECT StringToFix, FixedString, MyCounter, Id
FROM FixBadChars
WHERE MyCounter = 
        (SELECT MAX(MyCounter) 
        FROM FixBadChars Fixed
        WHERE Fixed.Id = FixBadChars.Id)
OPTION (MAXRECURSION 1000);

आपको केवल एक क्वेरी के बजाय एक अपडेट करने के लिए नीचे के हिस्से को संशोधित करने में सक्षम होना चाहिए, लेकिन मैंने वास्तव में इसकी कोशिश नहीं की है। मुझे पूरा यकीन है कि यह कुछ इस तरह दिखाई देगा:

UPDATE FixBadChars
SET StringToFix = FixedString
WHERE MyCounter = 
        (SELECT MAX(MyCounter) 
        FROM FixBadChars Fixed
        WHERE Fixed.Id = FixBadChars.Id)
OPTION (MAXRECURSION 1000);

जहाँ तक मापनीयता की बात है, मैंने 30 सेकंड के भीतर ~ 170k साफ पंक्तियों को वापस कर दिया। फिर से अपडेट करने के बारे में निश्चित नहीं है लेकिन यह मेरे लैपटॉप पर था जो केवल 6 जीबी रैम के साथ काफी धीमा है।


0
Declare @String nchar(2000)='hg$%^AB,.:23ab-=+'

Declare @NewString VARCHAR(2000)=''
Declare @Lenght int=LEN(@String)
Declare @Index int=1

WHILE (@Index <= @Lenght)
BEGIN
    Declare @Letter nchar(1)=Substring(@String,@Index,1);
    Declare @ASCII int=ASCII(@Letter);
    If((@ASCII >= 48 and @ASCII <= 57) or (@ASCII >= 97 and @ASCII <= 122) or (@ASCII >= 65 and @ASCII <= 90))
    BEGIN
        SET @NewString += @Letter
    END
    ELSE
    BEGIN
        SET @NewString += ' '
    END
    SET @Index+=1

END
Select @NewString
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.