La più grande difficoltà nel trovare una soluzione precisa è nel definire esattamente quali personaggi devono essere inclusi (o esclusi, qualunque direzione abbia più senso per l'operazione). Senso:
- Stiamo parlando di
VARCHAR
/ dati ASCII o dati NVARCHAR
/ Unicode? L'elenco dei caratteri di punteggiatura per i dati ASCII dipende dalla pagina del codice che a sua volta dipende dalla collazione. ( in questa domanda abbiamo a che fare con dati ASCII ).
- Abbiamo a che fare con ricerche con distinzione tra maiuscole e minuscole o senza distinzione tra maiuscole e minuscole?
- Su quale regole di confronto è impostata la colonna? La raccolta ci dirà sia la pagina di codice che la distinzione tra maiuscole e minuscole. ( in questa domanda abbiamo a che fare
Latin1_General_CI_AS
)
- è il termine "punteggiatura" per indicare solo i caratteri di punteggiatura standard (ad esempio
.
, ,
, ;
, :
, ecc) o lo fa caratteri medi non alfanumerici?
- Sono inclusi i caratteri degli spazi bianchi?
- I personaggi di controllo sono inclusi?
- Che dire di simboli di valuta come
¢
, £
, ¥
, ecc?
- Che dire di simboli come
©
e ™
?
- Quali personaggi sono considerati "alfa"? Sono caratteri non inglesi, come
Â
, É
, Ñ
, ß
, Þ
inclusi?
- Poiché questa domanda riguarda le tastiere del Regno Unito (vedi la discussione per questa domanda), che dire del carattere
Æ
/ æ
?
Al fine di facilitare la chiarezza sul comportamento previsto, la seguente query mostrerà tutti i 256 caratteri del set di caratteri Latin1 (ovvero Codice pagina 1252) e il funzionamento di due varianti della soluzione proposta da @ Shaneis . Il primo campo (etichettato come Latin1_General_CI_AS
) mostra la LIKE
clausola proposta da @Shaneis (al momento della stesura di questo documento) e il secondo campo (etichettato come Latin1_General_100_BIN2
) mostra una modifica in cui ho scavalcato la Collation per specificarne una binaria (ovvero una Collation che termina in _BIN2
; il _BIN
Le regole di confronto sono deprecate, quindi non utilizzarle se si ha accesso alle _BIN2
versioni), il che significa che ho anche bisogno di aggiungere l' A-Z
intervallo per filtrare le lettere maiuscole poiché l'attuale regole di confronto non fa distinzione tra maiuscole e minuscole:
;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;
AGGIORNARE
Va detto che SE uno sta veramente cercando di trovare caratteri classificati come "punteggiatura" (e non "simbolo di valuta", "simbolo matematico", ecc.), E SE non è proibito usare SQLCLR / caricare un costume Assembly (SQLCLR è stato introdotto con SQL Server 2005 e non ho ancora trovato una buona ragione per non consentirlo, soprattutto perché il database SQL Azure V12 supporta gli SAFE
assembly), quindi è possibile usare le espressioni regolari, ma non per il motivo che la maggior parte delle persone indovinerei.
Anziché utilizzare le espressioni regolari per creare un intervallo di caratteri più funzionale, o addirittura piuttosto che utilizzare qualcosa di simile \w
(ovvero qualsiasi carattere di "parola"), è possibile specificare la categoria Unicode dei caratteri su cui si desidera filtrare e ci sono diverse categorie definite :
https://www.regular-expressions.info/unicode.html#category
Puoi anche specificare il blocco Unicode su cui filtrare, come "InBengali" o "InDingbats" o "InOptical_Character_Recognition", ecc.
https://www.regular-expressions.info/unicode.html#block
Esistono numerosi esempi di creazione di funzioni RegEx per SQL Server (sebbene la maggior parte degli esempi non segua le best practice SQLCLR), oppure è possibile scaricare la versione gratuita della libreria SQL # (che ho creato) e utilizzare la funzione scalEx RegEx_IsMatch come segue :
SQL#.RegEx_IsMatch(Unicode-String-Expression, N'\p{P}', 1, NULL)
L' \p{P}
espressione significa \p
= categoria Unicode e {P}
= tutta la punteggiatura (al contrario di un tipo specifico di punteggiatura, come "Punteggiatura connettore"). E, la categoria "Punteggiatura" include tutta la punteggiatura in tutte le lingue! Puoi vedere l'elenco completo sul sito Unicode.org tramite il seguente link (al momento ci sono 717 punti di codice in quella categoria):
http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5B%3AGeneral_Category%3DPunctuation%3A%5D
Una versione aggiornata della query di test mostrata sopra, incluso un altro campo che utilizza SQL # .RegEx_IsMatch con \p{P}
, e i risultati di tutti e 3 i test su tutti i 256 caratteri di Code Page 1252 (cioè Latin1_General) è stata pubblicata su PasteBin.com all'indirizzo:
Query T-SQL e risultati per il filtraggio di tipi di caratteri
AGGIORNAMENTO
Nella discussione correlata è stato menzionato quanto segue:
Hai messo in evidenza i personaggi accentati, con i loro nomi di hotel da tutto il mondo ci saranno personaggi accentati nei nomi, per il mio problema vorrei classificarli come caratteri alfa validi.
In questo caso:
Esistono 11 caratteri non inglesi inclusi nel set di caratteri Latino1 / Pagina di codice che non corrispondono a-z
all'intervallo. Essi sono: ð Ð Þ þ œ Œ š Š ž Ž Ÿ
. Questi devono essere aggiunti al carattere jolly e, sebbene al momento non sia necessario, non farebbe male aggiungere in A-Z
modo che il modello funzioni altrettanto bene su un confronto sensibile al maiuscolo / minuscolo. Il risultato finale è:
LIKE '%[^a-zA-Z0-9ðÐÞþœŒšŠžŽŸ]%'
Considerando che questi dati possono includere "nomi di hotel di tutto il mondo", consiglio vivamente di modificare il tipo di dati della colonna in NVARCHAR
modo da poter memorizzare tutti i caratteri di tutte le lingue. Mantenere questo VARCHAR
rischio comporta un rischio molto elevato di avere alla fine la perdita di dati poiché è possibile rappresentare solo le lingue latine e nemmeno completamente per quelle date le sei categorie Unicode supplementari che forniscono caratteri aggiuntivi relativi al latino.