Уникальность текстового поля независимо от регистра

Здравствуйте! Подскажите, пожалуйста, как обеспечить уникальность текстового поля независимо от регистра наиболее оптимальным способом (скажем: есть таблица товаров, в которой название товара должно быть уникально, т.е. если есть, например, товар 'Коньки', то 'КоНькИ' вставить уже нельзя). Я вижу два варианта:
1) создание уникального индекса для поля:
CREATE UNIQUE INDEX index_for_full_product_uniqueness
ON products (upper(firstname))
2) создание триггерной функции и триггера для событий вставки и обновления. Триггерная функция будет выполняться для каждой вставляемой или обновляемой записи, при этом внутри её происходит выборка по таблице products:
SELECT INTO quantity_of_rows count(*) FROM products WHERE products.name ILIKE (NEW.name);
Ну, и далее проверяем: не больше ли ноля quantity_of_rows. Если больше генерируем исключение.

С одной стороны: первый вариант прост, с другой - индекс для текстового поля - это накладно, да и, все-таки, индекс первоначально предназначен не для создания ограничения.

Второй вариант, вроде бы, более логичен, т.к. создан триггер, который выполняет свои прямые обязанности. Но, учитывая, что триггер будет срабатывать для каждой изменяемой записи и при этом в триггерной функции будет каждый раз происходить операция выборки, такой подход кажется мне еще более накладным.

Что делать? Что выбрать? Может быть, есть еще какие-нибудь грамотные подходы?

Опции просмотра комментариев

Выберите предпочитаемый вами способ показа комментариев и нажмите "Сохранить настройки" для активации изменений.

> индекс первоначально

> индекс первоначально предназначен не для создания ограничения.
Вот тут вы ошибаетесь. Почти все ограничения целостности в PostgreSQL работают за счёт индексов: первичный ключ, внешний ключ, уникальность - все эти ограничения создают индексы.
Так что первый подход вполне себе нормальный.

Есть ещё и 3-й вариант. Используйте ограничение целостности CHECK:
http://postgresql.ru.net/manual/ddl-constraints.html#AEN2554

И 4-й вариант - создание своего типа данных, который не будет учитывать регистр букв.
В частности для работы 1C Бухгалтерии с PostgreSQL такой тип создан и называется mvchar. Однако, это нестандартный тип данных и PostgreSQL получается патченый, но возможно вам тупо будет удобней взять PostgreSQL от 1C?

Спасибо, за ответ!А я раньше

Спасибо, за ответ!

А я раньше думал, что индекс предназначен для ускорения операций обращения к данным.
Получается, вариант с индексом наиболее оптимален по логике, по простоте и по производительности (даже несмотря на то, что поле текстовое)?

Ограничение CHECK будет вызывать функцию проверки уникальности, такую же как и триггерная функция, так что триггеры и CHECK получаются идентичными

Не совсем. CHECK насколько я

Не совсем. CHECK насколько я понимаю построит индекс и будет его использовать :)

Извиняюсь, но что тогда

Извиняюсь, но что тогда должно быть в условии CHECK (чтобы обеспечить регистронезависимую уникальность текстового поля)? :)

А вот тут вы правы. Там

А вот тут вы правы. Там должно быть BOOLEAN, значит CHECK не подойдёт.

>Там должно быть BOOLEAN,

>Там должно быть BOOLEAN, значит CHECK не подойдёт.
Если только не написать функцию, которая будет возвращать логическое значение, и использовать её в CHECK. Но это будет то же самое , что и триггер с триггерной функцией. (Не эффективный и сложный вариант)  :))

Опции просмотра комментариев

Выберите предпочитаемый вами способ показа комментариев и нажмите "Сохранить настройки" для активации изменений.

Back to top

(С) Виктор Вислобоков, 2008-2023