Domanda

Sqlite3 per impostazione predefinita ordina solo per lettere ASCII. Ho provato a cercare su Google, ma l'unica cosa che ho trovato erano informazioni sulle regole di confronto. Sqlite3 ha solo regole di confronto NOCASE , RTRIM e BIARY . Come aggiungere il supporto per una locale specifica? (Lo sto usando nell'applicazione Rails)

È stato utile?

Soluzione

SQLite supporta l'integrazione con ICU . Secondo il file Leggimi, SQLite / ext / ICU / README.txt la directory sqlite / ext / icu / contiene il codice sorgente per l'ICU SQLite " estensione, un integrazione di "International Components for Unicode" libreria con SQLite.

1. Features

    1.1  SQL Scalars upper() and lower()
    1.2  Unicode Aware LIKE Operator
    1.3  ICU Collation Sequences
    1.4  SQL REGEXP Operator

Altri suggerimenti

Ho accettato la risposta di Doug Currie, ma voglio aggiungere un po 'di "algoritmo" come farlo, perché la documentazione di sqlite3 è molto strana (almeno per me).

Ok, abbiamo sqlite3 funzionante e ora:

  1. Scarica l'estensione ICU per sqlite

  2. Compilalo:

    gcc -shared icu.c `icu-config --ldflags` -o libSqliteIcu.so
    

    È per Linux. Avevo anche bisogno di installare un pacchetto di sviluppo ICU aggiuntivo:

    sudo apt-get install libicu-dev
    

    Sto lavorando su un'architettura a 64 bit e ricevo un errore con __relocation R_X86_64_32S__ (qualunque cosa significhi :). GCC ha suggerito di aggiungere -fPIC per compilare le opzioni e ha aiutato.

  3. Esegui sqlite3. Possiamo caricare l'estensione con il comando:

    .load './libSqliteIcu.so'
    

    Supponendo che si trovi nella directory corrente, possiamo anche specificare l'intero percorso.

  4. Crea nuove regole di confronto:

    SELECT icu_load_collation('pl_PL', 'POLISH');
    

    Il primo parametro è la locale desiderata e il secondo è (può essere qualunque cosa).

  5. Ora possiamo ordinare i dati con la nostra nuova locale:

    SELECT * FROM some_table ORDER BY name COLLATE POLISH;
    

    Ed è senza distinzione tra maiuscole e minuscole!

Se non puoi permetterti di compilare l'estensione ICU, puoi fare in modo che un UDF faccia lo stesso. In PHP / DOP:

$pdo->sqliteCreateFunction('locale',
    function ($data, $locale = 'root')
    {
        static $collators = array();

        if (isset($collators[$locale]) !== true)
        {
            $collators[$locale] = new \Collator($locale);
        }

        return $collators[$locale]->getSortKey($data);
    }
);

Esempio di utilizzo:

SELECT * FROM "table" ORDER BY locale("column", 'pt_PT');

Non mi aspetto che questo approccio sia efficiente come l'estensione nativa, ma è sicuramente più portatile.

Per coloro che non sono in grado di creare l'estensione da soli, ho reso disponibili versioni compilate per macOS e Linux qui: http://files.tempel.org/Various/Sqlite3ICUExtention

Le versioni di Linux, sia per Intel 32 che per 64 bit, sono state costruite su Ubuntu 16, se questo è importante.

Generalmente, non dovresti fidarti del codice compilato fornito da altri, ma sono una persona abbastanza pubblica, il che significa che correrei un rischio se fornissi un "cattivo" versione. E per essere sicuro che non ci siano attacchi man-in-the-middle o hack sul mio server, ecco gli hash MD5 per i 3 file:

libSqliteIcu-i386.so = 6decd73f27d9c61243128e798304508f
libSqliteIcu-x86_64.so = b127c8a1f65503c91c61a21732eb11be
sqlite3_icu_extension.dylib = a29d59f6b74e7ef234691729b82da660
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top