Ich versuche eine Abfrage zu schreiben, die die Sonderzeichen durch Leerzeichen ersetzt. Der folgende Code hilft bei der Identifizierung der Zeilen. (alphanumerische Zeichen, Komma und Leerzeichen sind gültig):
SELECT columnA
FROM tableA
WHERE columnA like '%[^a-Z0-9, ]%'
Wie kann ich die Ersetzungsfunktion in die select-Anweisung integrieren, sodass alle Zeichen außer alphanumerisch, Komma und Leerzeichen in der Ergebnismenge durch '' (Leerzeichen) ersetzt werden? Dieser wird nicht funktionieren:
SELECT replace(columnA,'%[^a-Z0-9, ]%',' ')
FROM tableA
WHERE columnA like '%[^a-Z0-9, ]%'
sql-server
sql-server-2008-r2
t-sql
replace
Stackoverflowuser
quelle
quelle
columnA
?Antworten:
Wenn Sie garantiert immer nur die 26 Buchstaben des englischen US-Alphabets (sowohl Groß- als auch Kleinbuchstaben) verwenden, können Sie sicher mit der Verwendung
LIKE
und / oderPATINDEX
der einfachen Bereichsnotation von[a-z]
(Sie würden es nicht tun) davonkommen müssen ein Großbuchstaben "Z" verwenden, wenn eine Sortierung ohne Berücksichtigung der Groß- / Kleinschreibung verwendet wird).Wenn Sie jedoch möglicherweise Zeichen erhalten, die noch nicht im US-Alphabet enthalten sind und noch in verschiedenen Codepages / Kollatierungen für
VARCHAR
Daten verfügbar sind (z. B.Þ
= lateinisches Großbuchstaben "Thorn" =SELECT CHAR(0xDE)
), müssen Sie diese möglicherweise in die Zeichenklasse aufnehmen :[a-z0-9, Þ]
. Diese zusätzlichen Zeichen werden natürlich pro Codepage verwendet.Beachten Sie außerdem, dass sowohl die Einstellungen für den Sortierungstyp (SQL Server vs Windows) als auch die Empfindlichkeitseinstellungen (Groß- und Kleinschreibung, Akzent usw., sensitiv oder unempfindlich) Einfluss darauf haben, welche Zeichen in einem bestimmten Bereich enthalten sind. Beispielsweise sortieren die SQL Server-Kollatierungen Groß- und Kleinbuchstaben in der entgegengesetzten Reihenfolge wie die Windows-Kollatierungen. Das heißt, unter der Annahme einer Sortierung, bei der zwischen Groß- und Kleinschreibung unterschieden wird, reicht eine
AaBb...
und die andere ausaAbB...
. Der Effekt wird sein, dass er für einen von ihnena
im Bereich von liegt,A-Z
für den anderen jedoch nicht. Und der Bereich vona-Z
stimmt nicht mit Zeichen in einer binären Kollatierung überein (eines endet entweder mit_BIN
oder_BIN2
, wird aber nicht verwendet_BIN
), vorausgesetzt, der Wert vonA
ist 65 unda
ist 97, daher ist es ein ungültiger Bereich von 97 bis 65 ;-). Es gibt viel zu viele Variationen, um hier Beispiele zu nennen, daher werde ich versuchen, bald eine ausführliche Erklärung in meinem Blog zu veröffentlichen (und diese dann mit dem Link dazu aktualisieren). Wenn Sie jedoch strengstens nur US-englische Zeichen akzeptieren (auch wenn Sie möglicherweise gültige Buchstaben aus anderen Sprachen erhalten), ist es wahrscheinlich die beste Option, das folgende Muster und die folgende Sortierung zu verwenden:Wenn Sie
NVARCHAR
Daten unterstützen und "Wort" -Zeichen aus verschiedenen Sprachen erhalten können, ist T-SQL keine große Hilfe, da es keine wirkliche Möglichkeit gibt, diese Dinge zu unterscheiden. In diesem Fall sollten Sie einen regulären Ausdruck (RegEx) verwenden - insbesondere dieReplace
Methode / Funktion - und diese sind nur über SQLCLR verfügbar. Das Folgende zeigt ein Beispiel für das Ersetzen mehrerer "Sonderzeichen", wobei jedoch alle gültigen Buchstaben in mindestens einer Sprache verbleiben:Kehrt zurück:
Der RegEx-Ausdruck bedeutet:
\W
= ein RegEx "Escape", was "ein beliebiges Nicht- Wort-Zeichen" bedeutet\p{Pc}
= eine Unicode "Kategorie" von "Interpunktion, Konnektor" (dies wird nur für die Übereinstimmung benötigt, da diese "Kategorie" durch das\W
Escape ausdrücklich ausgeschlossen wird )-[,]
= Klassensubtraktion (dies wird benötigt, um Kommas vom Abgleich als "speziell" auszuschließen, da sie im\W
Escape enthalten sind)Sie können eine Tabelle einfach aktualisieren, indem Sie Folgendes ausgeben:
Bitte beachten Sie, dass ich für diese Beispiele zwei Funktionen verwendet habe, die in der kostenlosen SQL # -Bibliothek der SQLCLR-Funktionen verfügbar sind, die ich erstellt habe (aber auch diese sind kostenlos). Beachten Sie auch, dass ich die "4k" -Versionen verwendet habe, die aufgrund der Verwendung
NVARCHAR(4000)
anstelle vonNVARCHAR(MAX)
Parametertypen schneller sind . Wenn Ihre Daten verwendet werdenNVARCHAR(MAX)
, entfernen Sie einfach die "4k" aus den Funktionsnamen.Bitte beachten Sie auch:
quelle
Ich habe hier einen Beitrag , der etwas Ähnliches macht .
Grundsätzlich verwende ich einen rekursiven CTE, um immer wieder eine Schleife zu durchlaufen und jeweils ein "schlechtes" Zeichen zu ersetzen. Ich verwende STUFF, um 1 Zeichen zu entfernen (obwohl Sie es verwenden können, um es durch ein Leerzeichen zu ersetzen) und PATINDEX, um die Position des Zeichens zu finden, das ich entfernen möchte. Sie können es leicht ändern, um das zu tun, wonach Sie suchen. Es wird jedoch eine "gute" Liste erstellt, die vorhandene Liste wird jedoch nicht aktualisiert.
Sie sollten in der Lage sein, den unteren Teil zu ändern, um ein Update und nicht nur eine Abfrage durchzuführen, aber ich habe es nicht wirklich versucht. Ich bin mir ziemlich sicher, dass es ungefähr so aussehen würde:
In Bezug auf die Skalierbarkeit habe ich in weniger als 30 Sekunden ~ 170.000 gereinigte Zeilen zurückgegeben. Wieder nicht sicher, ob ich ein Update durchführen soll, aber dies war auf meinem Laptop, der mit nur 6 GB RAM ziemlich langsam ist.
quelle
_BIN2
anstelle von verwenden_BIN
, aber zwei Hinweise: 1) Ich empfehle die Verwendung der neueren Version, die istLatin1_General_100_BIN2
. Noch wichtiger ist jedoch, 2) dass Sie durch Angabe einer binären Kollatierung versehentlich alle Buchstaben (beide Fälle) ausgeschlossen haben, da Großbuchstaben an erster Stelle stehen. Das heißt, der Bereich "gut" beginnt mit [97-90] in Bezug auf dezimale ASCII-Werte, was nichts entspricht. Um eine binäre Kollatierung zu verwenden, müssen Sie seinen ursprünglichen Ausdruck wie folgt ändern :[A-Za-z0-9, ]
. Dies schließt jedoch auch gültige Latin1-Zeichen mit Akzenten aus.A-Za-z
. Ich hätte es wahrscheinlich tun sollen. Obwohl ich sagen werde, dass es in meinen Tests richtig funktioniert hat (folgen Sie dem Link am Anfang).quelle