2016-06-15 2 views
2

J'ai remarqué un problème de collation étrange avec postgresql-9.5 car il donnait une sortie différente à un script Python. Si je comprends bien, les caractères normalement sont comparés un à la fois de gauche à droite lors du tri:Étrange collation avec postgresql

select 'ab' < 'ac'; 
t 

select 'abX' < 'ac'; 
t 

Il est donc hors de propos si vous ajoutez le « X » à la chaîne de la main gauche au-dessus.

donc j'ai été surpris quand cela ne tient pas la comparaison entre un espace et un tableau de bord:

select 'a ' < 'a-'; 
t 

select 'a X' < 'a-'; 
f 

Est-ce un bug ou est-il un moyen de contourner cela; Je veux que la dernière déclaration ci-dessus soit aussi vraie.


[Modifier après avoir accepté @ réponse de Laurenz-Albe]

show lc_collate; 
en_US.UTF-8 

Si je ne le tri par unicode en Python-je obtenir des résultats similaires il est donc pas un bogue dans postgresql, mais un bug dans le unicode spécification de classement à mon avis !:

>>> import locale; locale.setlocale(locale.LC_ALL, "") 
'en_US.UTF-8' 
>>> l = ['ac', 'ab']; sorted(l) == sorted(l, cmp=locale.strcoll) 
True 
>>> l = ['ac', 'abX']; sorted(l) == sorted(l, cmp=locale.strcoll) 
True 
>>> l = ['ac', 'abX']; sorted(l) == sorted(l, cmp=locale.strcoll) 
True 
>>> l = ['a-', 'a X']; sorted(l) == sorted(l, cmp=locale.strcoll) 
False 
>>> sorted(l), sorted(l, cmp=locale.strcoll) 
(['a X', 'a-'], ['a-', 'a X']) 
+0

efficacement sur deux Postgresql 9.1, sur Windows et Linux: sur les fenêtres de votre dernière requête return true, sur linux false, sur windows LC_COLLATE = 'C' et sur linux LC_COLLATE = 'tr_TR.UTF-8' –

Répondre

2

Les caractères sont comparés en utilisant une collation. Vous pouvez utiliser la commande SQL

SHOW lc_collate; 

pour voir quel est votre classement par défaut. PostgreSQL utilise les classements du système d'exploitation, de sorte que le résultat d'une comparaison dépendra souvent du système d'exploitation.

Pour forcer la comparaison ASCII sage octet, utilisez le classement C

test=> SELECT 'a X' COLLATE "C" < 'a-'; 
?column? 
---------- 
t 
(1 row) 

ou les opérateurs de comparaison sage octet

test=> SELECT 'a X' ~<~ 'a-'; 
?column? 
---------- 
t 
(1 row)