Perché il mio PostgreSQL ORDER BY non distingue tra maiuscole e minuscole?


27

Ho Postgres 9.4.4 in esecuzione su Debian e ottengo il seguente ORDER BYcomportamento:

veure_test=# show LC_COLLATE;
 lc_collate  
-------------
 en_US.UTF-8
(1 row)

veure_test=# SELECT regexp_split_to_table('D d a A c b CD Capacitor', ' ') ORDER BY 1;
 regexp_split_to_table 
-----------------------
 a
 A
 b
 c
 Capacitor
 CD
 d
 D
(8 rows)

E uname -a:

Linux ---- 3.2.0-4-amd64 #1 SMP Debian 3.2.65-1 x86_64 GNU/Linux

Tuttavia, sul mio iMac, con Postgres 9.3.4, ottengo quanto segue:

veure_test=# show LC_COLLATE;
 lc_collate  
-------------
 en_US.UTF-8
(1 row)

veure_test=# SELECT regexp_split_to_table('D d a A c b CD Capacitor', ' ') ORDER BY 1;
 regexp_split_to_table 
-----------------------
 A
 CD
 Capacitor
 D
 a
 b
 c
 d
(8 rows)

E il uname -a:

Darwin ---- 14.4.0 Darwin Kernel Version 14.4.0: Thu May 28 11:35:04 PDT 2015; root:xnu-2782.30.5~1/RELEASE_X86_64 x86_64

Sono sconcertato dal motivo per cui la versione di Debian non fa distinzione tra maiuscole e minuscole e la versione di OS X non lo è. Cosa mi manca o quali altre informazioni devo fornire?

Aggiornamento : sul mio Mac, la pg_collationtabella mostra che ho un en_US.UTF-8confronto, ma su Debian ho un en_US.utf8confronto. Quindi, sul mio Mac:

veure_test=# with foo as (
SELECT regexp_split_to_table('D d a A c b CD Capacitor', ' ') as bar
   )
SELECT bar FROM foo
ORDER BY bar collate "en_US.UTF-8";                                                                                                                                                                                      
    bar    
-----------
 A
 CD
 Capacitor
 D
 a
 b
 c
 d
(8 rows)

E su Debian:

veure_test=# with foo as (
SELECT regexp_split_to_table('D d a A c b CD Capacitor', ' ') as bar
   )
SELECT bar FROM foo
ORDER BY bar collate "en_US.utf8";
    bar    
-----------
 a
 A
 b
 c
 Capacitor
 CD
 d
 D
(8 rows)

Quindi en_US.UTF-8e en_US.utf8hai diversi ordinamenti?


Non ho un Mac su cui testare, quindi sto sparando al buio qui ... Qualche possibilità che la stringa 'D d a A c b CD Capacitor'non venga lanciata come un textcampo sul Mac? IE, prova a SELECT regexp_split_to_table('D d a A c b CD Capacitor'::text, ' ') ORDER BY 1;vedere cosa succede ...
Chris,

Stesso risultato In altre notizie, risulta che select * from pg_collationmostra la scatola Debian en_US.utf8, mentre l'OS X ha en_US.UTF-8. L'uso di questi per forzare esplicitamente le regole di confronto nelle rispettive caselle mostra diversi ordinamenti :(
Curtis Poe,

E ho pubblicato un aggiornamento che potrebbe spiegare il problema, ma per me non fa altro che approfondire il mistero. E ora ho trovato questo: stackoverflow.com/questions/19967555/… e questo: stackoverflow.com/questions/27395317/…
Curtis Poe,

7
Sfortunatamente Postgres utilizza l'implementazione delle regole di confronto dal sistema operativo che rende questo tipo di comportamento dipendente dal sistema operativo (che personalmente considero un bug: un DBMS dovrebbe comportarsi in modo identico indipendentemente dal sistema operativo). Quindi questo si riduce alle differenze nelle librerie di sistema tra Debian e OSX
a_horse_with_no_name

1
Ci sarà disaccordo tra Postgres e le altre parti del sistema se il criterio di ordinamento non è in linea con il resto. Anch'io preferisco un comportamento identico, ma non lo definirei un bug per seguire le impostazioni locali del sistema. In definitiva, locali identici dovrebbero comportarsi in modo identico su tutto il sistema operativo. Le impostazioni internazionali di Debian sembrano corrette , Apple sembra essere in errore (a meno che non ci siano altre spiegazioni).
Erwin Brandstetter,

Risposte:


16

Quindi en_US.UTF-8e en_US.utf8hai diversi ordinamenti?

No, entrambi sono uguali, solo una convenzione di denominazione diversa.

Sono sconcertato dal motivo per cui la versione di Debian non fa distinzione tra maiuscole e minuscole e la versione di OS X non lo è.

Sì hai ragione. Questo è il comportamento predefinito su Mac. Le regole di confronto non funzionano su alcun sistema operativo BSD (incl. OSX) per la UTF8codifica.

Ecco un riferimento per dimostrare che:

Problemi con l'ordinamento (le locali UTF8 non funzionano

Come diceva a_horse_with_no_name , Postgres utilizza l'implementazione delle regole di confronto dal sistema operativo. Non è possibile ottenere lo stesso risultato su entrambi i sistemi operativi.

Nel tuo caso si può (ho detto forse) fare in questo modo: ORDER BY lower(fieldname).


2
Prestare attenzione a verificare le prestazioni quando si utilizza ORDER BY function()su set di risultati potenzialmente di grandi dimensioni: poiché interrompe l'utilizzo di un indice per l'ordinamento, quasi sicuramente causerà un'operazione di ordinamento aggiuntiva (possibilmente su disco) e potrebbe cambiare il metodo del pianificatore di query per attaccare la query in modo più ampio .
David Spillett,

@ David Spillett: hai ragione sulla funzione Ordine. Penso che la mia risposta sia più focalizzata sul perché l'OP sta adottando una modalità di smistamento diversa in iMac e Debian. Grazie
JSapkota

1
Sì, la tua risposta è perfetta e copre completamente la domanda. La menzione di "test con dati reali dopo modifiche che potrebbero influenzare il piano di query" è diventata una reazione abituale in me (molto simile a menzionare i test in qualsiasi discussione sui backup e così via) in quanto è facile da dimenticare (e le persone spesso lo fanno) o nemmeno sapere nel caso di persone più nuove al lavoro sul database.
David Spillett,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.