2010-06-16 5 views
1

Est-il possible dans PostgreSQL pour convertir caractères UTF-8 à « similaires » des caractères ASCII?comparaison des chaînes dans PostgreSQL

Chaîne glāžšķūņu rūķīši devrait être converti en glazskunu rukisi. Le texte UTF-8 n'est pas dans une langue spécifique, il peut être en letton, russe, anglais, italien ou toute autre langue.

Ceci est nécessaire pour utiliser la clause where, il se peut donc que ce soit juste "comparer des chaînes" plutôt que "convertir des chaînes".

J'ai essayé d'utiliser convert, mais il ne donne pas les résultats escomptés (par exemple, select convert('Ā', 'utf8', 'sql_ascii') donne \304\200, non A).

Base de données est créée avec:

ENCODING = 'UTF8' 
LC_COLLATE = 'Latvian_Latvia.1257' 
LC_CTYPE = 'Latvian_Latvia.1257' 

Ces params peuvent être modifiées, le cas échéant.

+0

Je pense que vous allez avoir à écrire votre propre. Ensuite, nous pouvons tous l'utiliser! Ces fonctions –

Répondre

2

j'ai trouvé différentes façons de le faire sur le PostgreSQL Wiki.

En plperl:

CREATE OR REPLACE FUNCTION unaccent_string(text) RETURNS text AS $$ 
my ($input_string) = @_; 
$input_string =~ s/[âãäåāăą]/a; 
$input_string =~ s/[ÁÂÃÄÅĀĂĄ]/A; 
$input_string =~ s/[èééêëēĕėęě]/e; 
$input_string =~ s/[ĒĔĖĘĚ]/E; 
$input_string =~ s/[ìíîïìĩīĭ]/i; 
$input_string =~ s/[ÌÍÎÏÌĨĪĬ]/I; 
$input_string =~ s/[óôõöōŏő]/o; 
$input_string =~ s/[ÒÓÔÕÖŌŎŐ]/O; 
$input_string =~ s/[ùúûüũūŭů]/u; 
$input_string =~ s/[ÙÚÛÜŨŪŬŮ]/U; 
return $input_string; 
$$ LANGUAGE plperl; 

En pur SQL:

CREATE OR REPLACE FUNCTION unaccent_string(text) 
RETURNS text 
IMMUTABLE 
STRICT 
LANGUAGE SQL 
AS $$ 
SELECT translate(
    $1, 
    'âãäåāăąÁÂÃÄÅĀĂĄèééêëēĕėęěĒĔĖĘĚìíîïìĩīĭÌÍÎÏÌĨĪĬóôõöōŏőÒÓÔÕÖŌŎŐùúûüũūŭůÙÚÛÜŨŪŬŮ', 
    'aaaaaaaaaaaaaaaeeeeeeeeeeeeeeeiiiiiiiiiiiiiiiiooooooooooooooouuuuuuuuuuuuuuuu' 
); 
$$; 

Et plpython:

create or replace function unaccent(text) returns text language plpythonu as $$ 
import unicodedata 
rv = plpy.execute("select setting from pg_settings where name = 'server_encoding'"); 
encoding = rv[0]["setting"] 
s = args[0].decode(encoding) 
s = unicodedata.normalize("NFKD", s) 
s = ''.join(c for c in s if ord(c) < 127) 
return s 
$$; 

Dans votre cas, un translate() appeler avec tous les personnages que vous peut trouver dans le UTF-8 table devrait suffire.

+0

(auto-écrit) semblent être surpuissant ... – binaryLV

+0

Cette solution pure SQL est le meilleur que je pense que si vous avez besoin jeu de caractères quelque peu limitée (par exemple seulement des alphabets latin). Il sera rapide, facilement compréhensible et ne nécessite aucun module non standard. Il suffit d'obtenir tous les caractères de ISO-8859-1, ISO-8859-2 et ISO-8859-15 - cela devrait suffire. – Tometzky

+0

Pour l'instant, la fonction SQL pur est utilisée. Cependant, ce n'est pas aussi bon que je voudrais qu'il soit ... A propos des codages de caractères mentionnés - ce n'est pas assez, car il ne couvre pas le letton (je suis de Lettonie) et probablement beaucoup d'autres langues aussi - au moins ISO - 8859-4 devrait être ajouté. Pour le rendre plus complet, j'ai pris toutes les lettres avec diactrics de http://en.wikipedia.org/wiki/Diacritic (juste copié dans le bloc-notes tout le texte et enlevé tous les caractères "standard" en utilisant ctrl + h) et écrit égal lettres latines, puis rejoint avec des lettres d'exemples fournis par analogiques. – binaryLV

1

Utilisation pg_collkey() pour soins intensifs pris en charge unicode comparer: - http://www.public-software-group.org/pg_collkey - http://russ.garrett.co.uk/tag/postgresql/

+0

Impossible de l'essayer maintenant (je ne sais pas comment le compiler sous Windows). Et d'après ce que j'ai lu, je ne suis pas sûr que pg_collkey fonctionnerait pour nous, car nous devons utiliser des motifs simples, par exemple, la chaîne '% mazs% rukitis%' devrait correspondre 'mazs glāžšķūņu rūķītis'. – binaryLV