PostgreSQL 9.1 с использованием сортировки в операторах выбора - PullRequest
7 голосов
/ 17 октября 2011

У меня есть таблица базы данных postgresql 9.1, "en_US.UTF-8":

CREATE TABLE branch_language
(
    id serial NOT NULL,
    name_language character varying(128) NOT NULL,
    branch_id integer NOT NULL,
    language_id integer NOT NULL,
    ....
)

Атрибут name_language содержит имена на разных языках.Язык определяется внешним ключом language_id.

Я создал несколько индексов:

/* us english */
CREATE INDEX idx_branch_language_2
    ON branch_language
    USING btree
    (name_language COLLATE pg_catalog."en_US" );

/* catalan */
CREATE INDEX idx_branch_language_5
    ON branch_language
    USING btree
    (name_language COLLATE pg_catalog."ca_ES" );

/* portuguese */
CREATE INDEX idx_branch_language_6
    ON branch_language
    USING btree
    (name_language COLLATE pg_catalog."pt_PT" );

Теперь, когда я делаю выбор, я не получаю ожидаемых результатов.

select name_language from branch_language
where language_id=42 -- id of catalan language
order by name_language collate "ca_ES" -- use ca_ES collation

Это создает список имен, но не в том порядке, в котором я ожидал:

Aficions i Joguines
Agència de viatges
Aliments i Subministraments
Aparells elèctrics i il luminació
Art i Antiguitats
Articles de la llar
Bars i Restaurants
...
Tabac
Àudio, Vídeo, CD i DVD
Òptica

Как я и ожидал, две последние записи появятся в разных позициях в списке.

Создание индексов работает.Я не думаю, что они действительно необходимы, если вы не хотите оптимизировать производительность.

Однако оператор select, похоже, игнорирует часть: collate "ca_ES".

Эта проблема также возникает, когда явыберите другие сопоставления.Я пробовал "es_ES" и "pt_PT", но результаты схожи.

1 Ответ

3 голосов
/ 20 октября 2011

Я не могу найти недостаток в вашем дизайне. Я пытался.

Локали и сопоставление

Я вернулся к этому вопросу. Рассмотрим этот контрольный пример на sqlfiddle . Кажется, работает просто отлично. Я даже создал локаль ca_ES.utf8 на своем локальном тестовом сервере (PostgreSQL 9.1.6 на Debian Squeeze) и добавил локаль в мой кластер БД:

CREATE COLLATION "ca_ES" (LOCALE = 'ca_ES.utf8');

Я получаю те же результаты, что и в sqlfiddle выше.

Обратите внимание, что имена параметров сортировки являются идентификаторами и должны быть заключены в двойные кавычки для сохранения правописания CamelCase, например "ca_ES" Может быть, в вашей системе произошла путаница с другими локалями? Проверьте свои доступные параметры сортировки :

SELECT * FROM pg_collation;

Как правило, правила сопоставления получены из системных локалей . Подробнее о в руководстве читайте здесь . Если вы по-прежнему получаете неверные результаты, я попытался бы обновить вашу систему и восстановить языковой стандарт для "ca_ES". В Debian (и связанных дистрибутивах Linux) это можно сделать с помощью:

dpkg-reconfigure locales

NFC

У меня есть еще одна идея: ненормализованные строки UNICODE .

Может ли быть, что ваш 'Àudio' на самом деле '̀ ' || 'Audio'? Это был бы этот персонаж:

SELECT U&'\0300A';
SELECT ascii(U&'\0300A');
SELECT chr(768);

Подробнее о остром акценте в википедии .
Вы должны SET standard_conforming_strings = TRUE использовать строки Unicode, как в первой строке.

Обратите внимание, что некоторые браузеры не могут корректно отображать ненормализованные символы Юникода, и многие шрифты не имеют правильного символа для специальных символов, поэтому вы можете ничего не видеть здесь или тарабарщины. Но UNICODE допускает эту ерунду. Тест, чтобы увидеть, что вы получили:

SELECT octet_length('̀A')  -- returns 3 (!)
SELECT octet_length('À')  -- returns 2

Если это то, с чем ваша база данных заключила контракт, вам нужно от нее избавиться или пострадать от последствий. Лечение состоит в том, чтобы нормализовать ваши строки до NFC . Perl обладает превосходными навыками UNICODE-foo, вы можете использовать их библиотеки в функции plperlu для этого в PostgreSQL. Я сделал это, чтобы спасти меня от безумия.

Прочтите инструкции по установке в этой превосходной статье о нормализации UNICODE в PostgreSQL Дэвида Уилера .
Прочитайте все подробности о формах нормализации Unicode на unicode.org .

...