SQL सर्वर में स्ट्रिंग से सभी गैर-अल्फाबेटिक अक्षर कैसे छीनें?


172

आप उन सभी वर्णों को कैसे हटा सकते हैं जो एक तार से वर्णक्रमीय नहीं हैं?

गैर-अल्फ़ान्यूमेरिक के बारे में क्या?

क्या यह एक कस्टम फंक्शन होना चाहिए या इसके और भी सामान्य उपाय हैं?

जवाबों:


362

इस फ़ंक्शन का प्रयास करें:

Create Function [dbo].[RemoveNonAlphaCharacters](@Temp VarChar(1000))
Returns VarChar(1000)
AS
Begin

    Declare @KeepValues as varchar(50)
    Set @KeepValues = '%[^a-z]%'
    While PatIndex(@KeepValues, @Temp) > 0
        Set @Temp = Stuff(@Temp, PatIndex(@KeepValues, @Temp), 1, '')

    Return @Temp
End

इसे इस तरह से कॉल करें:

Select dbo.RemoveNonAlphaCharacters('abc1234def5678ghi90jkl')

एक बार जब आप कोड को समझ जाते हैं, तो आपको यह देखना चाहिए कि अन्य पात्रों को हटाने के लिए इसे बदलना अपेक्षाकृत सरल है। आप इस डायनामिक को भी अपने खोज पैटर्न में पास करने के लिए पर्याप्त बना सकते हैं।

आशा करता हूँ की ये काम करेगा।


9
यह कोड गैर-अल्फा वर्णों को हटाता है (इसलिए संख्याएँ भी हटा दी जाती हैं)। यदि आप संख्याओं को छोड़ना चाहते हैं (गैर-अल्फ़ा संख्यात्मक वर्णों को हटा दें), तो ... ^ az with ^ az ^ 0-9 प्रतिस्थापित करें यह खोज स्ट्रिंग कोड में दो अलग-अलग स्थानों में दिखाई देती है। उन दोनों को बदलना सुनिश्चित करें।
जॉर्ज मैस्ट्रोस

26
जेफ की टिप्पणी से: मुझे लगता है कि अगर सभी गैर-अक्षर और गैर-संख्याओं को छीनना चाहते हैं, तो आप '^ a-z0-9' (बनाम '^ az ^ 0-9') चाहते हैं, जो स्ट्रिंग में ^ छोड़ देगा) ।
यहां तक ​​कि मियां

1
+1 जॉर्ज। यह उन स्थानों में से एक है जहां "सेट-बेस्ड" कोड और इनलाइन स्केलर फ़ंक्शंस के उपयोग से रो-बाय-रो को बीट करने में बहुत कठिनाई होती है। अच्छी तरह से किया। मैं आपके "इनिशियल कैप्स" फंक्शन का भी उपयोग कर रहा हूं, जिसका एक ही मूल रूप है, कुछ वर्षों के लिए, अब।
जेफ मोडन

6
@ लिंची चेंज '% [^ az]%' से '% [^ az]%' मूल रूप से, बस z के बाद एक स्पेस कैरेक्टर डालें।
जॉर्ज मैस्ट्रोस

8
परिवर्तनीय नाम KeepValues ​​वास्तव में इसके विपरीत है जो यह करने के लिए है। KeepValues ​​उन वर्णों को सूचीबद्ध करता है जिन्हें बाहर करने की आवश्यकता है ..
nee21

167

जी मास्ट्रोस के भयानक उत्तर का पैरामीटर संस्करण :

CREATE FUNCTION [dbo].[fn_StripCharacters]
(
    @String NVARCHAR(MAX), 
    @MatchExpression VARCHAR(255)
)
RETURNS NVARCHAR(MAX)
AS
BEGIN
    SET @MatchExpression =  '%['+@MatchExpression+']%'

    WHILE PatIndex(@MatchExpression, @String) > 0
        SET @String = Stuff(@String, PatIndex(@MatchExpression, @String), 1, '')

    RETURN @String

END

केवल अक्षर:

SELECT dbo.fn_StripCharacters('a1!s2@d3#f4$', '^a-z')

केवल संख्यात्मक:

SELECT dbo.fn_StripCharacters('a1!s2@d3#f4$', '^0-9')

केवल अल्फान्यूमेरिक:

SELECT dbo.fn_StripCharacters('a1!s2@d3#f4$', '^a-z0-9')

गैर अक्षरांकीय:

SELECT dbo.fn_StripCharacters('a1!s2@d3#f4$', 'a-z0-9')

3
मैं इस संस्करण को पसंद करता हूं और इसे वोट करने के लिए नीचे स्क्रॉल करने से पहले जी मैस्ट्रोस के उत्तर का अपना अनुकूलन बनाया।
अर्जेन्टीना

रेगेक्स पैटर्न सभी व्हाट्सएप के साथ काम नहीं करता है। अगर मैं अल्फ़ान्यूमेरिक वर्णों और व्हाट्सएप को छोड़कर सभी विशेष पात्रों को छीनना चाहता हूं, तो मैं SELECT dbo.fn_StripCharacters('a1!s2 spaces @d3# f4$', '^a-z0-9\s')अभी भी व्हाट्सएप का उपयोग करने की उम्मीद करूंगा । मैंने भी उपयोग करने की कोशिश की, [[:blank:]]लेकिन यह फ़ंक्शन को तोड़ता है और स्ट्रिंग से कुछ भी नहीं निकाला जाता है। निकटतम Ive का उपयोग करके किया गया है: SELECT dbo.fn_StripCharacters('a1!s2 spaces @d3# f4$', '^a-z0-9 ')(regex पैटर्न में एक स्थान को हार्ड-कोड करना)। हालाँकि यह लाइन ब्रेक नहीं हटाता है।
बिली मैक्की

2
@BillyMcKee इसे रेग्युलर एक्सप्रेशन के अंत में जोड़ने के बजाय शुरुआत में स्पेस जोड़ें। SELECT dbo.fn_StripCharacters('a1!s2 spaces @d3# f4$', '^ a-z0-9')
माइक

8

मानो या न मानो, मेरे सिस्टम में यह बदसूरत फ़ंक्शन जी मास्ट्रोस सुरुचिपूर्ण से बेहतर प्रदर्शन करता है।

CREATE FUNCTION dbo.RemoveSpecialChar (@s VARCHAR(256)) 
RETURNS VARCHAR(256) 
WITH SCHEMABINDING
    BEGIN
        IF @s IS NULL
            RETURN NULL
        DECLARE @s2 VARCHAR(256) = '',
                @l INT = LEN(@s),
                @p INT = 1

        WHILE @p <= @l
            BEGIN
                DECLARE @c INT
                SET @c = ASCII(SUBSTRING(@s, @p, 1))
                IF @c BETWEEN 48 AND 57
                   OR  @c BETWEEN 65 AND 90
                   OR  @c BETWEEN 97 AND 122
                    SET @s2 = @s2 + CHAR(@c)
                SET @p = @p + 1
            END

        IF LEN(@s2) = 0
            RETURN NULL

        RETURN @s2

क्या सामान्य अल्पविराम, अवधि, स्थान, आदि के बारे में?
सजीम

कितना अलग है अगर आप ASCIIयहाँ पूर्णांक का उपयोग नहीं करते हैं और SUBSTRINGकुछ वर्णों के साथ सीधे उत्पादन की तुलना करते हैं , उदाहरण के लिए: SET @ch=SUBSTRING(@s, @p, 1)औरIF @ch BETWEEN '0' AND '9' OR @ch BETWEEN 'a' AND 'z' OR @ch BETWEEN 'A' AND 'Z' ...
S.Serpooshan

अपने समारोह में अपने समारोह की तरह SCHEMABINDING के साथ जोड़ें। आप VARCHAR का उपयोग कर रहे हैं, उनका फ़ंक्शन NVARCHAR का उपयोग कर रहा है। यदि आप उनके कार्य में गुजर रहे हैं तो VARCHAR हैं, तो आपको उनके फ़ंक्शन के भीतर NVARCHAR के बजाय VARCHAR का उपयोग करना चाहिए अन्यथा, आपके सिस्टम को फ़ंक्शन को निष्पादित करने से पहले VARCHAR से NVARCHAR तक स्ट्रिंग मान डालना होगा। यहां तक ​​कि उन परिवर्तनों के साथ आपका कार्य अभी भी तेज हो सकता है, लेकिन वे कुछ उदाहरण हैं जो मैं देख सकता हूं कि आपका कार्य आपकी स्थिति में आपके लिए धीमा प्रदर्शन कर सकता है।
एरिक

1
उनका फ़ंक्शन भी NVARCHAR (MAX) का उपयोग कर रहा है और आपका फ़ंक्शन VARCHAR (256) का उपयोग कर रहा है। यदि आपको सभी 256 की आवश्यकता है, तो VARCHAR (256) का उपयोग करने के लिए उसके फ़ंक्शन को बदलें और उसका कार्य आपके लिए तेजी से काम करेगा।
एरिक

5

मुझे पता था कि एसक्यूएल स्ट्रिंग हेरफेर में खराब था, लेकिन मुझे नहीं लगता था कि यह मुश्किल होगा। यहाँ एक स्ट्रिंग से सभी संख्याओं को निकालने का एक सरल कार्य है। ऐसा करने के लिए बेहतर तरीके होंगे, लेकिन यह एक शुरुआत है।

CREATE FUNCTION dbo.AlphaOnly (
    @String varchar(100)
)
RETURNS varchar(100)
AS BEGIN
  RETURN (
    REPLACE(
      REPLACE(
        REPLACE(
          REPLACE(
            REPLACE(
              REPLACE(
                REPLACE(
                  REPLACE(
                    REPLACE(
                      REPLACE(
                        @String,
                      '9', ''),
                    '8', ''),
                  '7', ''),
                '6', ''),
              '5', ''),
            '4', ''),
          '3', ''),
        '2', ''),
      '1', ''),
    '0', '')
  )
END
GO

-- ==================
DECLARE @t TABLE (
    ColID       int,
    ColString   varchar(50)
)

INSERT INTO @t VALUES (1, 'abc1234567890')

SELECT ColID, ColString, dbo.AlphaOnly(ColString)
FROM @t

उत्पादन

ColID ColString
----- ------------- ---
    1 abc1234567890 abc

राउंड 2 - डेटा-चालित ब्लैकलिस्ट

-- ============================================
-- Create a table of blacklist characters
-- ============================================
IF EXISTS (SELECT * FROM sys.tables WHERE [object_id] = OBJECT_ID('dbo.CharacterBlacklist'))
  DROP TABLE dbo.CharacterBlacklist
GO
CREATE TABLE dbo.CharacterBlacklist (
    CharID              int         IDENTITY,
    DisallowedCharacter nchar(1)    NOT NULL
)
GO
INSERT INTO dbo.CharacterBlacklist (DisallowedCharacter) VALUES (N'0')
INSERT INTO dbo.CharacterBlacklist (DisallowedCharacter) VALUES (N'1')
INSERT INTO dbo.CharacterBlacklist (DisallowedCharacter) VALUES (N'2')
INSERT INTO dbo.CharacterBlacklist (DisallowedCharacter) VALUES (N'3')
INSERT INTO dbo.CharacterBlacklist (DisallowedCharacter) VALUES (N'4')
INSERT INTO dbo.CharacterBlacklist (DisallowedCharacter) VALUES (N'5')
INSERT INTO dbo.CharacterBlacklist (DisallowedCharacter) VALUES (N'6')
INSERT INTO dbo.CharacterBlacklist (DisallowedCharacter) VALUES (N'7')
INSERT INTO dbo.CharacterBlacklist (DisallowedCharacter) VALUES (N'8')
INSERT INTO dbo.CharacterBlacklist (DisallowedCharacter) VALUES (N'9')
GO

-- ====================================
IF EXISTS (SELECT * FROM sys.objects WHERE [object_id] = OBJECT_ID('dbo.StripBlacklistCharacters'))
  DROP FUNCTION dbo.StripBlacklistCharacters
GO
CREATE FUNCTION dbo.StripBlacklistCharacters (
    @String nvarchar(100)
)
RETURNS varchar(100)
AS BEGIN
  DECLARE @blacklistCt  int
  DECLARE @ct           int
  DECLARE @c            nchar(1)

  SELECT @blacklistCt = COUNT(*) FROM dbo.CharacterBlacklist

  SET @ct = 0
  WHILE @ct < @blacklistCt BEGIN
    SET @ct = @ct + 1

    SELECT @String = REPLACE(@String, DisallowedCharacter, N'')
    FROM dbo.CharacterBlacklist
    WHERE CharID = @ct
  END

  RETURN (@String)
END
GO

-- ====================================
DECLARE @s  nvarchar(24)
SET @s = N'abc1234def5678ghi90jkl'

SELECT
    @s                  AS OriginalString,
    dbo.StripBlacklistCharacters(@s)   AS ResultString

उत्पादन

OriginalString           ResultString
------------------------ ------------
abc1234def5678ghi90jkl   abcdefghijkl

पाठकों के लिए मेरी चुनौती: क्या आप इसे अधिक कुशल बना सकते हैं? पुनरावर्तन का उपयोग करने के बारे में क्या?


आप शायद एक बेहतर dbo.StripBlacklistCharacters लिख सकते हैं () sommarskog.se/arrays-in-sql-2005.html#tblnum का उपयोग करते हुए एक लूप के बिना संख्या आपकी ब्लैक लिस्ट टेबल में शामिल हो गई, लेकिन मैं इसे आजमाने के लिए बहुत आलसी हूं। अपने आप को ....
केएम।

4

यदि आप मेरे जैसे हैं और आपके उत्पादन डेटा में केवल फ़ंक्शंस जोड़ने की पहुंच नहीं है, लेकिन फिर भी इस तरह की फ़िल्टरिंग करना चाहते हैं, तो यहां एक शुद्ध एसक्यूएल समाधान है जो फ़िल्टर किए गए टुकड़ों को फिर से एक साथ रखने के लिए एक PIVOT टेबल का उपयोग करता है।

नायब I ने 40 अक्षरों तक की तालिका को हार्डकोड किया, यदि आपके पास फ़िल्टर करने के लिए लंबे तार हैं, तो आपको अधिक जोड़ना होगा।

SET CONCAT_NULL_YIELDS_NULL OFF;

with 
    ToBeScrubbed
as (
    select 1 as id, '*SOME 222@ !@* #* BOGUS !@*&! DATA' as ColumnToScrub
),

Scrubbed as (
    select 
        P.Number as ValueOrder,
        isnull ( substring ( t.ColumnToScrub , number , 1 ) , '' ) as ScrubbedValue,
        t.id
    from
        ToBeScrubbed t
        left join master..spt_values P
            on P.number between 1 and len(t.ColumnToScrub)
            and type ='P'
    where
        PatIndex('%[^a-z]%', substring(t.ColumnToScrub,P.number,1) ) = 0
)

SELECT
    id, 
    [1]+ [2]+ [3]+ [4]+ [5]+ [6]+ [7]+ [8] +[9] +[10]
    +  [11]+ [12]+ [13]+ [14]+ [15]+ [16]+ [17]+ [18] +[19] +[20]
    +  [21]+ [22]+ [23]+ [24]+ [25]+ [26]+ [27]+ [28] +[29] +[30]
    +  [31]+ [32]+ [33]+ [34]+ [35]+ [36]+ [37]+ [38] +[39] +[40] as ScrubbedData
FROM (
    select 
        *
    from 
        Scrubbed
    ) 
    src
    PIVOT (
        MAX(ScrubbedValue) FOR ValueOrder IN (
        [1], [2], [3], [4], [5], [6], [7], [8], [9], [10],
        [11], [12], [13], [14], [15], [16], [17], [18], [19], [20],
        [21], [22], [23], [24], [25], [26], [27], [28], [29], [30],
        [31], [32], [33], [34], [35], [36], [37], [38], [39], [40]
        )
    ) pvt

235K पंक्तियों के सेट पर एक फ़ंक्शन का उपयोग करने की तुलना में मेरे लिए यह समाधान 2.3x तेज था। मुझे 2x प्रतिस्थापन भी करना था, और कुल चार सीटीई का उपयोग किया। एक विजेता की तरह काम किया।
JJS

4

सभी दिए गए समाधानों को देखने के बाद मैंने सोचा कि एक शुद्ध एसक्यूएल विधि होनी चाहिए जिसके लिए फ़ंक्शन या CTE / XML क्वेरी की आवश्यकता नहीं है, और नेस्टेड स्टेटमेंट स्टेटमेंट को बनाए रखने के लिए मुश्किल शामिल नहीं है। यहाँ मेरा समाधान है:

SELECT 
  x
  ,CASE WHEN a NOT LIKE '%' + SUBSTRING(x, 1, 1) + '%' THEN '' ELSE SUBSTRING(x, 1, 1) END
    + CASE WHEN a NOT LIKE '%' + SUBSTRING(x, 2, 1) + '%' THEN '' ELSE SUBSTRING(x, 2, 1) END
    + CASE WHEN a NOT LIKE '%' + SUBSTRING(x, 3, 1) + '%' THEN '' ELSE SUBSTRING(x, 3, 1) END
    + CASE WHEN a NOT LIKE '%' + SUBSTRING(x, 4, 1) + '%' THEN '' ELSE SUBSTRING(x, 4, 1) END
    + CASE WHEN a NOT LIKE '%' + SUBSTRING(x, 5, 1) + '%' THEN '' ELSE SUBSTRING(x, 5, 1) END
    + CASE WHEN a NOT LIKE '%' + SUBSTRING(x, 6, 1) + '%' THEN '' ELSE SUBSTRING(x, 6, 1) END
-- Keep adding rows until you reach the column size 
    AS stripped_column
FROM (SELECT 
        column_to_strip AS x
        ,'ABCDEFGHIJKLMNOPQRSTUVWXYZ' AS a 
      FROM my_table) a

इस तरह से करने का लाभ यह है कि वैध वर्णों को एक स्ट्रिंग में एक अलग स्ट्रिंग में समाहित किया जाता है जिससे वर्णों के एक अलग सेट के लिए पुन: कॉन्फ़िगर करना आसान हो जाता है।

नकारात्मक पक्ष यह है कि आपको अपने कॉलम के आकार तक प्रत्येक वर्ण के लिए SQL की एक पंक्ति को जोड़ना होगा। उस कार्य को आसान बनाने के लिए मैंने नीचे Powershell स्क्रिप्ट का उपयोग किया है, उदाहरण के लिए यदि VARCHAR (64) के लिए:

1..64 | % {
  "    + CASE WHEN a NOT LIKE '%' + SUBSTRING(x, {0}, 1) + '%' THEN '' ELSE SUBSTRING(x, {0}, 1) END" -f $_
} | clip.exe

3
सामान्य मामले में अजीब, लेकिन संकीर्ण कॉलम के साथ एक बार-बंद क्वेरी के लिए आसान और उपयोगी।
एरिक जे।

3

यहाँ गैर-अक्षर वर्णों को हटाने का एक और तरीका है a iTVF। सबसे पहले, आपको एक पैटर्न-आधारित स्ट्रिंग स्प्लिटर की आवश्यकता है। यहाँ ड्वायन कैंप के लेख से एक लिया गया है :

-- PatternSplitCM will split a string based on a pattern of the form 
-- supported by LIKE and PATINDEX 
-- 
-- Created by: Chris Morris 12-Oct-2012 
CREATE FUNCTION [dbo].[PatternSplitCM]
(
       @List                VARCHAR(8000) = NULL
       ,@Pattern            VARCHAR(50)
) RETURNS TABLE WITH SCHEMABINDING 
AS 

RETURN
    WITH numbers AS (
        SELECT TOP(ISNULL(DATALENGTH(@List), 0))
            n = ROW_NUMBER() OVER(ORDER BY (SELECT NULL))
        FROM
        (VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) d (n),
        (VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) e (n),
        (VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) f (n),
        (VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) g (n)
    )

    SELECT
        ItemNumber = ROW_NUMBER() OVER(ORDER BY MIN(n)),
        Item = SUBSTRING(@List,MIN(n),1+MAX(n)-MIN(n)),
        [Matched]
    FROM (
        SELECT n, y.[Matched], Grouper = n - ROW_NUMBER() OVER(ORDER BY y.[Matched],n)
        FROM numbers
        CROSS APPLY (
            SELECT [Matched] = CASE WHEN SUBSTRING(@List,n,1) LIKE @Pattern THEN 1 ELSE 0 END
        ) y
    ) d
    GROUP BY [Matched], Grouper

अब जब आपके पास एक पैटर्न-आधारित फाड़नेवाला है, तो आपको पैटर्न से मेल खाने वाले तारों को विभाजित करने की आवश्यकता है:

[a-z]

और फिर उन्हें वांछित परिणाम प्राप्त करने के लिए वापस जाएं:

SELECT *
FROM tbl t
CROSS APPLY(
    SELECT Item + ''
    FROM dbo.PatternSplitCM(t.str, '[a-z]')
    WHERE Matched = 1
    ORDER BY ItemNumber
    FOR XML PATH('')
) x (a)

नमूना

परिणाम:

| Id |              str |              a |
|----|------------------|----------------|
|  1 |    testte d'abc |     testtedabc |
|  2 |            anr¤a |           anra |
|  3 |  gs-re-C“te d'ab |     gsreCtedab |
|  4 |         Mfe, DF |          MfeDF |
|  5 |           Rtemd |          Rtemd |
|  6 |          jadji |          jadji |
|  7 |      Cje y ret¢n |       Cjeyretn |
|  8 |        Jklbalu |        Jklbalu |
|  9 |       lene-iokd |       leneiokd |
| 10 |   liode-Pyrnie |    liodePyrnie |
| 11 |         Vs Gta |          VsGta |
| 12 |        Sƒo Paulo |        SoPaulo |
| 13 |  vAstra gAtaland | vAstragAtaland |
| 14 |  ¥uble / Bio-Bio |     ubleBioBio |
| 15 | Upln/ds VAsb-y |    UplndsVAsby |

क्या इसका अन्य उत्तरों पर उपयोग करने का कोई फायदा है?
एस। सेरपोशन

2

श्री एलेन के समाधान से प्रेरित इस समाधान Numbersके लिए पूर्णांक की एक तालिका की आवश्यकता होती है (जो आपको अच्छे प्रदर्शन के साथ गंभीर क्वेरी संचालन करना चाहते हैं)। इसके लिए CTE की आवश्यकता नहीं है। आप बदल सकते हैं NOT IN (...)विशिष्ट वर्ण बाहर करने के लिए अभिव्यक्ति है, या एक के लिए इसे बदल IN (...)या LIKEअभिव्यक्ति केवल विशेष केरेक्टर्स बनाए रखने के लिए।

SELECT (
    SELECT  SUBSTRING([YourString], N, 1)
    FROM    dbo.Numbers
    WHERE   N > 0 AND N <= CONVERT(INT, LEN([YourString]))
        AND SUBSTRING([YourString], N, 1) NOT IN ('(',')',',','.')
    FOR XML PATH('')
) AS [YourStringTransformed]
FROM ...

एक असंबंधित मुद्दे का दिलचस्प समाधान।
TaterJuice

2

यहाँ एक समाधान है जिसे किसी फ़ंक्शन को बनाने या वर्णों के सभी उदाहरणों को सूचीबद्ध करने की आवश्यकता नहीं है। यह अवांछित चार्ट खोजने के लिए PATINDEX के साथ संयोजन में कथन के साथ एक पुनरावर्ती का उपयोग करता है। यह एक स्तंभ में सभी अवांछित वर्णों को बदल देगा - किसी भी स्ट्रिंग में निहित 100 अद्वितीय बुरे वर्ण तक। (उदा। "ABC123DEF234" में 4 बुरे वर्ण 1, 2, 3 और 4 शामिल होंगे। 100 सीमा बिना किसी कथन के अनुमत अधिकतम संख्या है, लेकिन यह प्रक्रिया करने के लिए पंक्तियों की संख्या पर सीमा नहीं लगाती है, जो केवल उपलब्ध स्मृति द्वारा सीमित है।
यदि आप DISTINCT परिणाम नहीं चाहते हैं, तो आप कोड से दो विकल्प निकाल सकते हैं।

-- Create some test data:
SELECT * INTO #testData 
FROM (VALUES ('ABC DEF,K.l(p)'),('123H,J,234'),('ABCD EFG')) as t(TXT)

-- Actual query:
-- Remove non-alpha chars: '%[^A-Z]%'
-- Remove non-alphanumeric chars: '%[^A-Z0-9]%'
DECLARE @BadCharacterPattern VARCHAR(250) = '%[^A-Z]%';

WITH recurMain as (
    SELECT DISTINCT CAST(TXT AS VARCHAR(250)) AS TXT, PATINDEX(@BadCharacterPattern, TXT) AS BadCharIndex
    FROM #testData
    UNION ALL
    SELECT CAST(TXT AS VARCHAR(250)) AS TXT, PATINDEX(@BadCharacterPattern, TXT) AS BadCharIndex
    FROM (
        SELECT 
            CASE WHEN BadCharIndex > 0 
                THEN REPLACE(TXT, SUBSTRING(TXT, BadCharIndex, 1), '')
                ELSE TXT 
            END AS TXT
        FROM recurMain
        WHERE BadCharIndex > 0
    ) badCharFinder
)
SELECT DISTINCT TXT
FROM recurMain
WHERE BadCharIndex = 0;

1

मैंने इसे उन दोनों स्थानों पर रखा है जहां पैटींडेक्स कहा जाता है।

PatIndex('%[^A-Za-z0-9]%', @Temp)

RemoveNonAlphaCharacters के ऊपर कस्टम फ़ंक्शन के लिए और इसका नाम RemoveNonAlphaNumericCharacters


1

- एक समारोह बनाएँ

CREATE FUNCTION [dbo].[GetNumericonly]
(@strAlphaNumeric VARCHAR(256))
RETURNS VARCHAR(256)
AS
BEGIN
     DECLARE @intAlpha INT
     SET @intAlpha = PATINDEX('%[^0-9]%', @strAlphaNumeric)
BEGIN
     WHILE @intAlpha > 0
   BEGIN
          SET @strAlphaNumeric = STUFF(@strAlphaNumeric, @intAlpha, 1, '' )
          SET @intAlpha = PATINDEX('%[^0-9]%', @strAlphaNumeric )
   END
END
RETURN ISNULL(@strAlphaNumeric,0)
END

अब इस फ़ंक्शन को कॉल करें

select [dbo].[GetNumericonly]('Abhi12shek23jaiswal')

इसके परिणाम की तरह

1223

1

प्रदर्शन के दृष्टिकोण से मैं इनलाइन फ़ंक्शन का उपयोग करूंगा:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [dbo].[udf_RemoveNumericCharsFromString]
(
@List NVARCHAR(4000)
)
RETURNS TABLE 
AS RETURN

    WITH GetNums AS (
       SELECT TOP(ISNULL(DATALENGTH(@List), 0))
        n = ROW_NUMBER() OVER(ORDER BY (SELECT NULL))
        FROM
          (VALUES (0),(0),(0),(0)) d (n),
          (VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) e (n),
          (VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) f (n),
          (VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) g (n)
            )

    SELECT StrOut = ''+
        (SELECT Chr
         FROM GetNums
            CROSS APPLY (SELECT SUBSTRING(@List , n,1)) X(Chr)
         WHERE Chr LIKE '%[^0-9]%' 
         ORDER BY N
         FOR XML PATH (''),TYPE).value('.','NVARCHAR(MAX)')


   /*How to Use
   SELECT StrOut FROM dbo.udf_RemoveNumericCharsFromString ('vv45--9gut')
   Result: vv--gut
   */

मुझे पता है कि यह धागा पुराना है लेकिन, इनलाइन टेबल वैल्यू फंक्शन जाने का रास्ता है। आपके समाधान के साथ समस्या यह है, क्योंकि आप केवल संख्याएँ, यह कोड:), टाइप करें) .value ('।', 'NVARCHAR (MAX)') की आवश्यकता नहीं है और यह कार्य को ~ 50% से धीमा कर देगा
एलन बुर्स्टीन

1

यहाँ @Gerhard Weiss के उत्तर के आधार पर एक और पुनरावर्ती CTE समाधान दिया गया है । आपको SSMS में पूरे कोड ब्लॉक को कॉपी और पेस्ट करने में सक्षम होना चाहिए और वहां उसके साथ खेलना चाहिए। परिणामों में कुछ अतिरिक्त कॉलम शामिल हैं जो हमें यह समझने में मदद करते हैं कि क्या हो रहा है। जब तक मुझे समझ नहीं आया तब तक मुझे PATINDEX (RegEx) और पुनरावर्ती CTE दोनों के साथ चलना है।

DECLARE @DefineBadCharPattern varchar(30)
SET @DefineBadCharPattern = '%[^A-z]%'  --Means anything NOT between A and z characters (according to ascii char value) is "bad"
SET @DefineBadCharPattern = '%[^a-z0-9]%'  --Means anything NOT between a and z characters or numbers 0 through 9 (according to ascii char value) are "bad"
SET @DefineBadCharPattern = '%[^ -~]%'  --Means anything NOT between space and ~ characters (all non-printable characters) is "bad"
--Change @ReplaceBadCharWith to '' to strip "bad" characters from string
--Change to some character if you want to 'see' what's being replaced. NOTE: It must be allowed accoring to @DefineBadCharPattern above
DECLARE @ReplaceBadCharWith varchar(1) = '#'  --Change this to whatever you want to replace non-printable chars with 
IF patindex(@DefineBadCharPattern COLLATE Latin1_General_BIN, @ReplaceBadCharWith) > 0
    BEGIN
        RAISERROR('@ReplaceBadCharWith value (%s) must be a character allowed by PATINDEX pattern of %s',16,1,@ReplaceBadCharWith, @DefineBadCharPattern)
        RETURN
    END
--A table of values to play with:
DECLARE @temp TABLE (OriginalString varchar(100))
INSERT @temp SELECT ' 1hello' + char(13) + char(10) + 'there' + char(30) + char(9) + char(13) + char(10)
INSERT @temp SELECT '2hello' + char(30) + 'there' + char(30)
INSERT @temp SELECT ' 3hello there'
INSERT @temp SELECT ' tab' + char(9) + ' character'
INSERT @temp SELECT 'good bye'

--Let the magic begin:
;WITH recurse AS (
    select
    OriginalString,
    OriginalString as CleanString,
    patindex(@DefineBadCharPattern COLLATE Latin1_General_BIN, OriginalString) as [Position],
    substring(OriginalString,patindex(@DefineBadCharPattern COLLATE Latin1_General_BIN, OriginalString),1) as [InvalidCharacter],
    ascii(substring(OriginalString,patindex(@DefineBadCharPattern COLLATE Latin1_General_BIN, OriginalString),1)) as [ASCIICode]
    from @temp
   UNION ALL
    select
    OriginalString,
    CONVERT(varchar(100),REPLACE(CleanString,InvalidCharacter,@ReplaceBadCharWith)),
    patindex(@DefineBadCharPattern COLLATE Latin1_General_BIN,CleanString) as [Position],
    substring(CleanString,patindex(@DefineBadCharPattern COLLATE Latin1_General_BIN,CleanString),1),
    ascii(substring(CleanString,patindex(@DefineBadCharPattern COLLATE Latin1_General_BIN,CleanString),1))
    from recurse
    where patindex(@DefineBadCharPattern COLLATE Latin1_General_BIN,CleanString) > 0
)
SELECT * FROM recurse
--optionally comment out this last WHERE clause to see more of what the recursion is doing:
WHERE patindex(@DefineBadCharPattern COLLATE Latin1_General_BIN,CleanString) = 0

0

प्रत्येक वर्ण की जांच करने के लिए CTE जनरेट की गई संख्या तालिका का उपयोग करना, फिर XML के लिए आपके द्वारा रखे जा सकने वाले मानों की एक स्ट्रिंग को समाप्‍त करना ...

CREATE FUNCTION [dbo].[PatRemove](
    @pattern varchar(50),
    @expression varchar(8000) 
    )
RETURNS varchar(8000)
AS
BEGIN
    WITH 
        d(d) AS (SELECT d FROM (VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) digits(d)),
        nums(n) AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM d d1, d d2, d d3, d d4),
        chars(c) AS (SELECT SUBSTRING(@expression, n, 1) FROM nums WHERE n <= LEN(@expression))
    SELECT 
        @expression = (SELECT c AS [text()] FROM chars WHERE c NOT LIKE @pattern FOR XML PATH(''));

    RETURN @expression;
END

0
DECLARE @vchVAlue NVARCHAR(255) = 'SWP, Lettering Position 1: 4 Ω, 2: 8 Ω, 3: 16 Ω, 4:  , 5:  , 6:  , Voltage Selector, Solder, 6, Step switch, : w/o fuseholder '


WHILE PATINDEX('%?%' , CAST(@vchVAlue AS VARCHAR(255))) > 0
  BEGIN
    SELECT @vchVAlue = STUFF(@vchVAlue,PATINDEX('%?%' , CAST(@vchVAlue AS VARCHAR(255))),1,' ')
  END 

SELECT @vchVAlue

0

इस तरह से मेरे लिए काम नहीं किया क्योंकि मैं अरबी अक्षरों को रखने की कोशिश कर रहा था जो मैंने नियमित अभिव्यक्ति को बदलने की कोशिश की, लेकिन यह भी काम नहीं किया। मैंने ASCII स्तर पर काम करने के लिए एक और विधि लिखी क्योंकि यह मेरी एकमात्र पसंद थी और इसने काम किया।

 Create function [dbo].[RemoveNonAlphaCharacters] (@s varchar(4000)) returns varchar(4000)
   with schemabinding
begin
   if @s is null
      return null
   declare @s2 varchar(4000)
   set @s2 = ''
   declare @l int
   set @l = len(@s)
   declare @p int
   set @p = 1
   while @p <= @l begin
      declare @c int
      set @c = ascii(substring(@s, @p, 1))
      if @c between 48 and 57 or @c between 65 and 90 or @c between 97 and 122 or @c between 165 and 253 or @c between 32 and 33
         set @s2 = @s2 + char(@c)
      set @p = @p + 1
      end
   if len(@s2) = 0
      return null
   return @s2
   end

जाओ


-1

हालांकि पोस्ट थोड़ा पुराना है, मैं निम्नलिखित कहना चाहूंगा। मेरे पास उपरोक्त समाधान के साथ समस्या यह है कि यह ç, ë, with, आदि जैसे वर्णों को फ़िल्टर नहीं करता है, मैंने एक फ़ंक्शन को निम्नानुसार अनुकूलित किया (मैंने मेमोरी बचाने के लिए केवल 80 varchar string का उपयोग किया है):

create FUNCTION dbo.udf_Cleanchars (@InputString varchar(80)) 
RETURNS varchar(80) 
AS 

BEGIN 
declare @return varchar(80) , @length int , @counter int , @cur_char char(1) 
SET @return = '' 
SET @length = 0 
SET @counter = 1 
SET @length = LEN(@InputString) 
IF @length > 0 
BEGIN WHILE @counter <= @length 

BEGIN SET @cur_char = SUBSTRING(@InputString, @counter, 1) IF ((ascii(@cur_char) in (32,44,46)) or (ascii(@cur_char) between 48 and 57) or (ascii(@cur_char) between 65 and 90) or (ascii(@cur_char) between 97 and 122))
BEGIN SET @return = @return + @cur_char END 
SET @counter = @counter + 1 
END END 

RETURN @return END

इसके लिए धन्यवाद, एरिक। जैसा कि आप कहते हैं, पोस्ट चिह्नित उत्तर बहुत अच्छा है, लेकिन यह नासमझ "संख्यात्मक" वर्णों को post की तरह पट्टी नहीं करता है।
ट्रॉय

-3

मैंने अभी इसे Oracle 10g में बनाया है यदि आप इसका उपयोग कर रहे हैं। मुझे फोन नंबर की तुलना के लिए सभी विशेष पात्रों को उतारना पड़ा।

regexp_replace(c.phone, '[^0-9]', '')

5
"SQL सर्वर" विशेष रूप से Microsoft के उत्पाद को संदर्भित करता है।
कोई भी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.