Wie können Sie alle nicht alphabetischen Zeichen aus einer Zeichenfolge entfernen?
Was ist mit nicht alphanumerischen?
Muss dies eine benutzerdefinierte Funktion sein oder gibt es auch allgemeinere Lösungen?
Wie können Sie alle nicht alphabetischen Zeichen aus einer Zeichenfolge entfernen?
Was ist mit nicht alphanumerischen?
Muss dies eine benutzerdefinierte Funktion sein oder gibt es auch allgemeinere Lösungen?
Antworten:
Versuchen Sie diese Funktion:
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
Nennen Sie es so:
Select dbo.RemoveNonAlphaCharacters('abc1234def5678ghi90jkl')
Sobald Sie den Code verstanden haben, sollten Sie feststellen, dass es relativ einfach ist, ihn zu ändern, um auch andere Zeichen zu entfernen. Sie können diese sogar dynamisch genug gestalten, um Ihr Suchmuster weiterzugeben.
Ich hoffe es hilft.
Parametrisierte Version von G Mastros ' großartiger Antwort :
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
Nur alphabetisch:
SELECT dbo.fn_StripCharacters('a1!s2@d3#f4$', '^a-z')
Nur numerisch:
SELECT dbo.fn_StripCharacters('a1!s2@d3#f4$', '^0-9')
Nur alphanumerisch:
SELECT dbo.fn_StripCharacters('a1!s2@d3#f4$', '^a-z0-9')
Nicht alphanumerisch:
SELECT dbo.fn_StripCharacters('a1!s2@d3#f4$', 'a-z0-9')
SELECT dbo.fn_StripCharacters('a1!s2 spaces @d3# f4$', '^a-z0-9\s')
noch Leerzeichen entfernt werden. Ich habe auch versucht zu verwenden, [[:blank:]]
aber das bricht die Funktion und nichts wird aus der Zeichenfolge entfernt. Das nächste, was ich bekommen habe, ist die Verwendung von: SELECT dbo.fn_StripCharacters('a1!s2 spaces @d3# f4$', '^a-z0-9 ')
(hartes Codieren eines Leerzeichens im Regex-Muster). Zeilenumbrüche werden dadurch jedoch nicht entfernt.
SELECT dbo.fn_StripCharacters('a1!s2 spaces @d3# f4$', '^ a-z0-9')
Ob Sie es glauben oder nicht, in meinem System ist diese hässliche Funktion besser als die elegante von G Mastros.
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
Ganzzahl verwenden und die Ausgabe von direkt SUBSTRING
mit einigen Zeichen vergleichen, z. B.: SET @ch=SUBSTRING(@s, @p, 1)
undIF @ch BETWEEN '0' AND '9' OR @ch BETWEEN 'a' AND 'z' OR @ch BETWEEN 'A' AND 'Z' ...
Ich wusste, dass SQL schlecht in der Manipulation von Zeichenfolgen ist, aber ich dachte nicht, dass es so schwierig sein würde. Hier ist eine einfache Funktion, um alle Zahlen aus einer Zeichenfolge zu entfernen. Es gibt bessere Möglichkeiten, dies zu tun, aber dies ist ein Anfang.
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
Ausgabe
ColID ColString
----- ------------- ---
1 abc1234567890 abc
Runde 2 - Datengesteuerte Blacklist
-- ============================================
-- 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
Ausgabe
OriginalString ResultString
------------------------ ------------
abc1234def5678ghi90jkl abcdefghijkl
Meine Herausforderung an die Leser: Können Sie dies effizienter gestalten? Was ist mit Rekursion?
Wenn Sie wie ich sind und nicht nur Funktionen zu Ihren Produktionsdaten hinzufügen können, aber dennoch diese Art der Filterung durchführen möchten, finden Sie hier eine reine SQL-Lösung, die eine PIVOT-Tabelle verwendet, um die gefilterten Teile wieder zusammenzusetzen.
NB Ich habe die Tabelle mit bis zu 40 Zeichen fest codiert. Sie müssen mehr hinzufügen, wenn Sie längere Zeichenfolgen zum Filtern haben.
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
Nachdem ich mir alle gegebenen Lösungen angesehen hatte, dachte ich, dass es eine reine SQL-Methode geben muss, die keine Funktion oder eine CTE / XML-Abfrage erfordert und keine schwierig zu verwaltenden verschachtelten REPLACE-Anweisungen beinhaltet. Hier ist meine Lösung:
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
Der Vorteil dieser Vorgehensweise besteht darin, dass die gültigen Zeichen in der einen Zeichenfolge in der Unterabfrage enthalten sind, sodass die Konfiguration für einen anderen Zeichensatz einfach ist.
Der Nachteil ist, dass Sie für jedes Zeichen bis zur Größe Ihrer Spalte eine SQL-Zeile hinzufügen müssen. Um diese Aufgabe zu vereinfachen, habe ich nur das folgende Powershell-Skript verwendet, dieses Beispiel für ein VARCHAR (64):
1..64 | % {
" + CASE WHEN a NOT LIKE '%' + SUBSTRING(x, {0}, 1) + '%' THEN '' ELSE SUBSTRING(x, {0}, 1) END" -f $_
} | clip.exe
Hier ist eine andere Möglichkeit, nicht alphabetische Zeichen mit einem zu entfernen iTVF
. Zunächst benötigen Sie einen musterbasierten String-Splitter. Hier ist einer aus dem Artikel von Dwain Camp :
-- 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
Nachdem Sie einen musterbasierten Splitter haben, müssen Sie die Zeichenfolgen teilen, die dem Muster entsprechen:
[a-z]
und verketten Sie sie dann wieder, um das gewünschte Ergebnis zu erzielen:
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)
Ergebnis:
| Id | str | a |
|----|------------------|----------------|
| 1 | test“te d'abc | testtedabc |
| 2 | anr¤a | anra |
| 3 | gs-re-C“te d'ab | gsreCtedab |
| 4 | M‚fe, DF | MfeDF |
| 5 | R™temd | Rtemd |
| 6 | ™jad”ji | jadji |
| 7 | Cje y ret¢n | Cjeyretn |
| 8 | J™kl™balu | Jklbalu |
| 9 | le“ne-iokd | leneiokd |
| 10 | liode-Pyr‚n‚ie | liodePyrnie |
| 11 | V„s G”ta | VsGta |
| 12 | Sƒo Paulo | SoPaulo |
| 13 | vAstra gAtaland | vAstragAtaland |
| 14 | ¥uble / Bio-Bio | ubleBioBio |
| 15 | U“pl™n/ds VAsb-y | UplndsVAsby |
Diese Lösung, die von Mr. Allens Lösung inspiriert ist, erfordert eine Numbers
Tabelle mit ganzen Zahlen (die Sie zur Hand haben sollten, wenn Sie ernsthafte Abfragevorgänge mit guter Leistung ausführen möchten). Es ist kein CTE erforderlich. Sie können den NOT IN (...)
Ausdruck ändern , um bestimmte Zeichen auszuschließen, oder ihn in einen IN (...)
ODER- LIKE
Ausdruck ändern , um nur bestimmte Zeichen beizubehalten.
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 ...
Hier ist eine Lösung, bei der keine Funktion erstellt oder alle zu ersetzenden Zeicheninstanzen aufgelistet werden müssen. Es verwendet eine rekursive WITH-Anweisung in Kombination mit einem PATINDEX, um unerwünschte Zeichen zu finden. Es ersetzt alle unerwünschten Zeichen in einer Spalte - bis zu 100 eindeutige fehlerhafte Zeichen in einer bestimmten Zeichenfolge. (EG "ABC123DEF234" würde 4 fehlerhafte Zeichen 1, 2, 3 und 4 enthalten.) Das Limit von 100 ist die maximale Anzahl von Rekursionen, die in einer WITH-Anweisung zulässig sind. Dies legt jedoch kein Limit für die Anzahl der zu verarbeitenden Zeilen fest ist nur durch den verfügbaren Speicher begrenzt.
Wenn Sie keine UNTERSCHIEDLICHEN Ergebnisse wünschen, können Sie die beiden Optionen aus dem Code entfernen.
-- 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;
Ich habe dies an beiden Stellen platziert, an denen PatIndex aufgerufen wird.
PatIndex('%[^A-Za-z0-9]%', @Temp)
für die benutzerdefinierte Funktion über RemoveNonAlphaCharacters und benenne sie in RemoveNonAlphaNumericCharacters um
- Erstellen Sie zuerst eine Funktion
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
Rufen Sie diese Funktion nun wie auf
select [dbo].[GetNumericonly]('Abhi12shek23jaiswal')
Sein Ergebnis gefällt
1223
Aus Sicht der Leistung würde ich die Inline-Funktion verwenden:
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
*/
Hier ist eine weitere rekursive CTE-Lösung, die auf der Antwort von @Gerhard Weiss hier basiert . Sie sollten in der Lage sein, den gesamten Codeblock zu kopieren und in SSMS einzufügen und dort damit zu spielen. Die Ergebnisse enthalten einige zusätzliche Spalten, damit wir besser verstehen, was los ist. Es dauerte eine Weile, bis ich alles verstand, was sowohl mit PATINDEX (RegEx) als auch mit dem rekursiven CTE vor sich geht.
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
Verwenden Sie eine von CTE generierte Zahlentabelle, um jedes Zeichen zu untersuchen, und dann FOR XML, um sich auf eine Zeichenfolge von beibehaltenen Werten zu konzentrieren, die Sie ...
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
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
Dieser Weg funktionierte nicht für mich, da ich versuchte, die arabischen Buchstaben beizubehalten. Ich versuchte, den regulären Ausdruck zu ersetzen, aber es funktionierte auch nicht. Ich habe eine andere Methode geschrieben, um auf ASCII-Ebene zu arbeiten, da dies meine einzige Wahl war und funktioniert hat.
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
GEHEN
Obwohl der Beitrag etwas alt ist, möchte ich Folgendes sagen. Das Problem, das ich mit der obigen Lösung hatte, ist, dass Zeichen wie ç, ë, ï usw. nicht herausgefiltert werden. Ich habe eine Funktion wie folgt angepasst (ich habe nur eine 80-varchar-Zeichenfolge verwendet, um Speicher zu sparen):
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
Ich habe gerade festgestellt, dass dies in Oracle 10g integriert ist, wenn Sie es verwenden. Ich musste alle Sonderzeichen entfernen, um die Telefonnummer vergleichen zu können.
regexp_replace(c.phone, '[^0-9]', '')