Die größte Schwierigkeit, eine genaue Lösung zu finden, besteht darin, genau zu definieren , welche Zeichen eingeschlossen (oder ausgeschlossen) werden sollen, je nachdem, welche Richtung für die Operation sinnvoller ist. Bedeutung:
- Sprechen wir über
VARCHAR
/ ASCII-Daten oder NVARCHAR
/ Unicode-Daten? Die Liste der Satzzeichen für ASCII-Daten hängt von der Codepage ab, die wiederum von der Sortierung abhängt. ( In dieser Frage beschäftigen wir uns mit ASCII-Daten ).
- Handelt es sich um Suchanfragen, bei denen zwischen Groß- und Kleinschreibung unterschieden wird?
- Auf welche Sortierung ist die Spalte eingestellt? In der Sortierung werden sowohl die Codepage als auch die Groß- und Kleinschreibung angegeben. ( In dieser Frage haben wir es zu tun
Latin1_General_CI_AS
)
- ist der Begriff „Zeichensetzung“ nur Standardsatzzeichen (zB bedeuten
.
, ,
, ;
, :
, usw.) oder bedeutet es , nicht-alphanumerische Zeichen?
- Sind Leerzeichen enthalten?
- Sind Steuerzeichen enthalten?
- Was über Währungssymbole wie
¢
, £
, ¥
, etc?
- Was ist mit Symbolen wie
©
und ™
?
- Welche Zeichen gelten als "Alpha"? Sind nicht-englische Zeichen wie
Â
, É
, Ñ
, ß
, Þ
enthalten?
- Was ist mit dem / -Zeichen, da sich diese Frage mit Tastaturen in Großbritannien befasst (siehe Diskussion zu dieser Frage) ?
Æ
æ
Um die Klarheit hinsichtlich des erwarteten Verhaltens zu verbessern, werden in der folgenden Abfrage alle 256 Zeichen des Latin1-Zeichensatzes (dh Code Seite 1252) und die Funktionsweise von zwei Varianten der von @ Shaneis vorgeschlagenen Lösung angezeigt . Das erste Feld (gekennzeichnet als Latin1_General_CI_AS
) zeigt die LIKE
von @Shaneis vorgeschlagene Klausel (zum Zeitpunkt dieses Schreibens) und das zweite Feld (gekennzeichnet als Latin1_General_100_BIN2
) zeigt eine Modifikation, bei der ich die Kollatierung überschrieben habe, um eine binäre anzugeben (dh eine Kollatierung, die mit endet _BIN2
; _BIN
Sortierungen sind veraltet, verwenden Sie sie also nicht, wenn Sie Zugriff auf die _BIN2
Versionen haben. Dies bedeutete, dass ich auch den A-Z
Bereich hinzufügen musste, um Großbuchstaben herauszufiltern, da bei der aktuellen Sortierung die Groß- und Kleinschreibung nicht berücksichtigt wird:
;WITH nums AS
(
SELECT TOP (256) (ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1) AS [Decimal]
FROM [master].[sys].[all_objects]
)
SELECT nm.[Decimal],
CHAR(nm.[Decimal]) AS [Character],
CASE WHEN CHAR(nm.[Decimal]) LIKE '%[^a-z0-9]%'
THEN 'x' ELSE '' END AS [Latin1_General_CI_AS],
CASE WHEN CHAR(nm.[Decimal]) LIKE '%[^a-z0-9A-Z]%' COLLATE Latin1_General_100_BIN2
THEN 'x' ELSE '' END AS [Latin1_General_100_BIN2]
FROM nums nm;
AKTUALISIEREN
Es sollte erwähnt werden, dass WENN man wirklich versucht, Zeichen zu finden, die als "Interpunktion" (und nicht als "Währungssymbol", "mathematisches Symbol" usw.) klassifiziert sind, und WENN es nicht verboten ist, SQLCLR zu verwenden / einen Benutzer zu laden Assembly (SQLCLR wurde mit SQL Server 2005 eingeführt, und ich habe noch keinen guten Grund gefunden, dies nicht zuzulassen, insbesondere da Azure SQL Database V12 SAFE
Assemblies unterstützt ). Dann können Sie reguläre Ausdrücke verwenden, jedoch nicht aus dem Grund, den die meisten Benutzer verwenden würde raten.
Anstatt reguläre Ausdrücke zu verwenden, um einen funktionaleren Zeichenbereich zu erstellen, oder sogar etwas wie \w
(dh ein "Wort" -Zeichen) zu verwenden, können Sie die Unicode-Kategorie der Zeichen angeben, nach denen Sie filtern möchten, und es gibt mehrere definierte Kategorien ::
https://www.regular-expressions.info/unicode.html#category
Sie können sogar den Unicode-Block angeben, nach dem gefiltert werden soll, z. B. "InBengali" oder "InDingbats" oder "InOptical_Character_Recognition" usw.:
https://www.regular-expressions.info/unicode.html#block
Es gibt zahlreiche Beispiele zum Erstellen von RegEx-Funktionen für SQL Server (obwohl die meisten Beispiele nicht den bewährten Methoden von SQLCLR entsprechen), oder Sie können die kostenlose Version der SQL # -Bibliothek (die ich erstellt habe) herunterladen und die skalare RegEx_IsMatch- Funktion wie folgt verwenden ::
SQL#.RegEx_IsMatch(Unicode-String-Expression, N'\p{P}', 1, NULL)
Der \p{P}
Ausdruck bedeutet \p
= Unicode-Kategorie und {P}
= alle Interpunktion (im Gegensatz zu einer bestimmten Art von Interpunktion, wie z. B. "Connector-Interpunktion"). UND, die Kategorie "Interpunktion" umfasst alle Interpunktionen in allen Sprachen! Sie können die vollständige Liste auf der Unicode.org-Website über den folgenden Link anzeigen (derzeit befinden sich 717 Codepunkte in dieser Kategorie):
http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5B%3AGeneral_Category%3DPunctuation%3A%5D
Eine aktualisierte Version der Testabfrage oben gezeigt, einschließlich eines anderen Feld , das verwendet SQL # .RegEx_IsMatch mit \p{P}
, und die Ergebnisse aller drei Tests für alle 256 Zeichen von Codepage 1252 (dh Latin1_General) hat auf PasteBin.com bei gepostet:
T-SQL-Abfrage und Ergebnisse zum Filtern von Zeichentypen
UPDATE
Folgendes wurde in der zugehörigen Diskussion erwähnt:
Sie haben einen guten Punkt in Bezug auf akzentuierte Zeichen gemacht, da es sich um Hotelnamen aus der ganzen Welt handelt. Die Namen enthalten akzentuierte Zeichen. Für mein Problem möchte ich diese als gültige Alpha-Zeichen klassifizieren.
In diesem Fall:
Der Latin1-Zeichensatz / die Codepage enthält 11 nicht englische Zeichen, die nicht mit dem a-z
Bereich übereinstimmen . Sie sind : ð Ð Þ þ œ Œ š Š ž Ž Ÿ
. Diese müssen dem Platzhalter hinzugefügt werden, und obwohl dies im Moment nicht erforderlich ist, würde es nicht schaden, sie hinzuzufügen, A-Z
damit das Muster bei einer Sortierung mit Groß- und Kleinschreibung genauso gut funktioniert. Das Endergebnis ist:
LIKE '%[^a-zA-Z0-9ðÐÞþœŒšŠžŽŸ]%'
In Anbetracht der Tatsache, dass diese Daten "Hotelnamen aus der ganzen Welt" enthalten können, würde ich dringend empfehlen, den Datentyp der Spalte so zu ändern NVARCHAR
, dass Sie alle Zeichen aus allen Sprachen speichern können. Wenn Sie dies VARCHAR
beibehalten, besteht ein sehr hohes Risiko für Datenverluste, da Sie nur die lateinischen Sprachen darstellen können und nicht einmal vollständig für diejenigen, die die sechs zusätzlichen Unicode-Kategorien enthalten, die zusätzliche lateinische Zeichen enthalten.