2012-05-04 6 views
5

Per esempio, questo è l'ordine che un 'ordinare per nome' standard di interrogazione sta tornando:Come posso controllare l'ordinamento UTF-8 in MySQL?

name 
------ 
Cebbb 
Čebbc 
Cebbd 

mi piacerebbe ordinare per nome e ottenere il carattere accentato prima, raggruppati con altri caratteri accentati , per esempio

name 
------ 
Čebbc 
Cebbb 
Cebbd 

Per impostazione predefinita, MySql tratta i Č come se fosse C, a fini di smistamento, e specie nell'ordine indicato.

In alternativa, c'è un modo, in PHP, che posso 'convertire' Č in C, a scopo di confronto?

risposta

2

Il modo più semplice è quello di applicare un metodo di confronto adeguata alla colonna stessa, ad esempio:

CREATE TABLE foo (
    foo_id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, 
    `name` VARCHAR(30) NOT NULL COLLATE 'utf8_spanish_ci', 
    PRIMARY KEY (`foo_id`) 
) 
COLLATE='utf8_spanish_ci' 
ENGINE=InnoDB; 

Aggiornamento:

Č non è una lettera spagnola:

Negli alfabeti croato, sloveno, bosniaco, Skolt Sami e Lakota, è è la quarta lettera dell'alfabeto. Nell'alfabeto Sami ceco, settentrionale e nelle lingue baltiche lituano e lettone, la lettera è in quinto posto. In slovacco è sesta lettera dell'alfabeto. È anche utilizzato in Pashto (equivalente a چ) e Saanich.

A differenza dei numeri, le lettere non hanno un ordine assoluto fisso. L'intero concetto di ordine alfabetico è relativo: devi prima scegliere un insieme di regole. Eseguire la query SQL per sapere quali sono disponibili nel server MySQL:

SHOW CHARACTER SET 

... e ha scelto quello che meglio si adatta alle vostre aspettative. C'è un brief description nel manuale.

+0

Quando si dice "corretto", ciò include utf8_general_ci? Questo è ciò che la tabella e la colonna sono già specificate, e non sarà incredibilmente facile cambiarlo, dal momento che il database non è "mio" (è fornito da joomla) –

+0

"Corretto" dipende dalla lingua. Ci sono diverse regole quando si ordina il testo. Se 'utf8_spanish_ci' è il tuo attuale confronto, qual è il tuo problema esatto? Non vuoi le moderne regole spagnole o non le ottieni? –

+0

Ah - Vedo il problema. Stai dicendo che Č è un personaggio spagnolo? In questo contesto, in realtà non è (o non viene utilizzato in spagnolo), ma - spero - questo non è rilevante. Ci sarà un sacco di personaggi di diverse lingue. Se è assurdo provare a trattare Č come C, allora sono felice * non *, ma questo ritorna al problema originale che MySQL * sta * trattandoli come uguali. –

6

È possibile add a COLLATE expression to your ORDER BY clause:

SELECT k 
FROM t1 
ORDER BY k COLLATE utf8_spanish_ci; 

Poi, la colonna verranno ordinati utilizzando la fascicolazione corretta, e la definizione di colonna può rimanere così com'è.

+0

Penso che la domanda originale fosse confusa; Ho aggiornato per chiarire. –

+0

La soluzione di Yogu sembra rispondere alla tua domanda. Con le regole di confronto corrette, SQL ordinerà i caratteri in qualsiasi ordine corretto per quella lingua. – Cylindric

0

Per sostituire i caratteri speciali come quelli con accenti o dieresi dai caratteri latini ordinarie, è possibile utilizzare la funzione PHP iconv:

iconv("UTF-8", "ASCII//TRANSLIT", $text) 

Questo convertirà la variabile $text in caratteri ASCII puri. Ad esempio, Müssig sarà convertita in muessig e grani in caffee.

+0

anche se non so come la soluzione * alternativa * sia correlata alla tua domanda principale – Yogu

+0

La soluzione alternativa mi permetterebbe di trattare i due caratteri come gli stessi in PHP, permettendomi di raggrupparli sotto un'intestazione comune. Sto ricevendo le righe dal DB, quindi emettendo un '' intestazione 'quando il carattere iniziale cambia - come un elenco di indici in un libro. Attualmente sto ricevendo un elenco di nomi "C", seguito da un nome "Č", seguito da un altro elenco di nomi "C". –

+0

Ah ok, quindi la soluzione php sembra essere la migliore, perché sicuramente non vuoi una sezione per ogni carattere speciale. – Yogu

0

OK, ecco mia soluzione a ciò che è, certamente, un bel special-case:

ORDER BY SUBSTRING(name, 1, 1), 
     BINARY SUBSTRING(name, 1, 1), 
     name 

Questo non è certamente la query più efficiente - in questo caso, però, che non è troppo grande una preoccupazione - ma fa risolvere il mio problema:

  1. Ordina per il carattere iniziale (in cui MySql tratterà Č e C come identici)
  2. Poi ordini dal valore binario del carattere iniziale, che differenziare Č e C
  3. Poi ordinazione dal nome completo, che sarà - in effetti - ordine dal resto della stringa.

Questo ordinerà in modo non ottimale dopo il primo carattere, ma non è un problema.

+0

Diminuzione drastica - spiegazione? –