Sto lavorando con un database MySQL che ha alcuni dati importati da Excel . I dati contengono caratteri non ASCII (trattini em, ecc.) Nonché ritorni a capo nascosti o avanzamenti riga. C'è un modo per trovare questi record usando MySQL?
Sto lavorando con un database MySQL che ha alcuni dati importati da Excel . I dati contengono caratteri non ASCII (trattini em, ecc.) Nonché ritorni a capo nascosti o avanzamenti riga. C'è un modo per trovare questi record usando MySQL?
Risposte:
Dipende esattamente da cosa stai definendo "ASCII", ma ti suggerirei di provare una variante di una query come questa:
SELECT * FROM tableName WHERE columnToCheck NOT REGEXP '[A-Za-z0-9]';
Quella query restituirà tutte le righe in cui columnToCheck contiene caratteri non alfanumerici. Se hai altri caratteri accettabili, aggiungili alla classe di caratteri nell'espressione regolare. Ad esempio, se punti, virgole e trattini sono corretti, modificare la query in:
SELECT * FROM tableName WHERE columnToCheck NOT REGEXP '[A-Za-z0-9.,-]';
La pagina più rilevante della documentazione di MySQL è probabilmente 12.5.2 Regular Expressions .
SELECT * FROM tbl WHERE colname NOT REGEXP '^[A-Za-z0-9\.,@&\(\) \-]*$';
MySQL fornisce una gestione completa del set di caratteri che può aiutare con questo tipo di problema.
SELECT whatever
FROM tableName
WHERE columnToCheck <> CONVERT(columnToCheck USING ASCII)
La CONVERT(col USING charset)
funzione trasforma i caratteri non convertibili in caratteri sostitutivi. Quindi, il testo convertito e non convertito sarà diverso.
Vedi questo per ulteriori discussioni. https://dev.mysql.com/doc/refman/8.0/en/charset-repertoire.html
È possibile utilizzare qualsiasi nome di set di caratteri desiderato al posto di ASCII. Ad esempio, se vuoi scoprire quali caratteri non verranno visualizzati correttamente nella tabella codici 1257 (lituano, lettone, estone) usaCONVERT(columnToCheck USING cp1257)
Puoi definire ASCII come tutti i caratteri che hanno un valore decimale compreso tra 0 e 127 (0x00 - 0x7F) e trovare colonne con caratteri non ASCII utilizzando la seguente query
SELECT * FROM TABLE WHERE NOT HEX(COLUMN) REGEXP '^([0-7][0-9A-F])*$';
Questa è stata la domanda più completa che ho potuto fare.
SELECT * FROM table WHERE LENGTH( column ) != CHAR_LENGTH( column )
'ā'
(codificato dalla sequenza di byte 0x0101
) - sarebbe considerato "ASCII" utilizzando questo test: un falso negativo ; anzi, alcuni set di caratteri Non caratteri ASCII codificare all'interno 0x00
di 0x7f
al che questa soluzione darebbe un falso positivo. NON AFFIDATEVI A QUESTA RISPOSTA!
LENGTH(column)
saranno un multiplo costante CHAR_LENGTH(column)
indipendentemente dal valore.
Questo è probabilmente quello che stai cercando:
select * from TABLE where COLUMN regexp '[^ -~]';
Dovrebbe restituire tutte le righe in cui COLUMN contiene caratteri non ASCII (o caratteri ASCII non stampabili come la nuova riga).
REGEXP
e RLIKE
funzionano in modo byte-wise, quindi non sono sicuri multibyte e possono produrre risultati imprevisti con set di caratteri multibyte. Inoltre, questi operatori confrontano i caratteri in base ai loro valori byte e i caratteri accentati potrebbero non essere paragonabili allo stesso modo anche se un dato confronto li considera uguali. "
Un carattere mancante dagli esempi di tutti sopra è il carattere di terminazione (\ 0). Questo è invisibile all'output della console MySQL e non è rilevabile da nessuna delle query precedentemente menzionate. La query per trovarlo è semplicemente:
select * from TABLE where COLUMN like '%\0%';
Basandomi sulla risposta corretta, ma tenendo conto anche dei caratteri di controllo ASCII, la soluzione che ha funzionato per me è questa:
SELECT * FROM `table` WHERE NOT `field` REGEXP "[\\x00-\\xFF]|^$";
Fa la stessa cosa: cerca le violazioni dell'intervallo ASCII in una colonna, ma ti consente anche di cercare i caratteri di controllo, poiché utilizza la notazione esadecimale per i punti di codice. Poiché non vi è alcun confronto o conversione (a differenza della risposta di @ Ollie), anche questo dovrebbe essere significativamente più veloce. (Soprattutto se MySQL esegue la terminazione anticipata sulla query regex, cosa che dovrebbe sicuramente.)
Evita inoltre di restituire campi di lunghezza zero. Se desideri una versione leggermente più lunga che possa funzionare meglio, puoi utilizzare questa:
SELECT * FROM `table` WHERE `field` <> "" AND NOT `field` REGEXP "[\\x00-\\xFF]";
Esegue un controllo separato per la lunghezza per evitare risultati di lunghezza zero, senza considerarli per un passaggio di regex. A seconda del numero di voci di lunghezza zero che hai, questo potrebbe essere significativamente più veloce.
Nota che se il tuo set di caratteri predefinito è qualcosa di bizzarro in cui 0x00-0xFF non si associa agli stessi valori di ASCII (esiste un set di caratteri di questo tipo da qualche parte?), Ciò restituirebbe un falso positivo. Altrimenti, divertiti!
REGEXP
sta controllando. Quindi è garantito che corrisponda sempre. Inoltre ^$
probabilmente non è quello che volevi.
In Oracle possiamo usare di seguito.
SELECT * FROM TABLE_A WHERE ASCIISTR(COLUMN_A) <> COLUMN_A;
per questa domanda possiamo usare anche questo metodo:
Domanda da sql zoo:
Trova tutti i dettagli del premio vinto da PETER GRÜNBERG
Caratteri non ASCII
ans: seleziona * da nobel dove vincitore like'P% GR% _% berg ';