Перейти к основному содержимому

citext. Тип данных для строк, нечувствительных к регистру

В исходном дистрибутиве установлено по умолчанию: нет.

Связанные компоненты: отсутствуют.

Схема размещения: ext.

Модуль предоставляет тип данных citext для строк, нечувствительных к регистру. Сравнивая значения, он вызывает внутри себя функцию lower(). В остальном почти не отличается от типа text.

Стандартный способ с использованием функции lower() при сравнении значений имеет ряд недостатков:

  • необходимо всегда обрабатывать функцией lower столбец и значение;
  • для использования индекса необходимо создать функциональный индекс с функцией lower;
  • при работе со столбцами типа UNIQUE или PRIMARY KEY неявно создаваемый индекс будет чувствительным к регистру. Соответственно он не сможет использоваться при регистронезависимом поиске, а также не будет обеспечивать уникальность вне учета регистра.

Применение типа данных citext позволяет исключить вызовы функции lower() в SQL-запросах и позволяет сделать первичный ключ регистронезависимым.

Типы text и citext учитывают локаль. Это означает, что сравнение символов в верхнем и нижнем регистре зависит от правил LC_CTYPE для базы данных. Такое поведение идентично использованию функции lower() в запросах, и поскольку оно реализуется прозрачно типам данных, в самих запросах ничего дополнительно делать не нужно.

Доработка

Доработка не проводилась.

Ограничения

Существуют следующие ограничения:

  • Смена регистра символов в citext зависит от параметра LC_CTYPE вашей базы данных. Принцип, используемый при сравнении значений, определяется на этапе ее создания. Здесь важно учитывать, что сравнение не будет действительно регистронезависимым. Так, если установленное правило сортировки предназначено для одного языка, а в БД имеются данные на разных языках, то пользователи могут получать неожиданные результаты запросов.
  • Операторы citext принимают во внимание явное указание COLLATE, сравнивая строки в нижнем регистре, но изначальное приведение в нижний регистр всегда выполняется согласно параметру LC_CTYPE базы данных, как если бы указывалось COLLATE "default";
  • Тип citext не так эффективен, как text, поскольку функции операторов и функции сравнения для B-дерева должны делать копии данных и переводить их в нижний регистр для сравнения. Кроме того, с типом text возможно исключение дубликатов в B-дереве. Тем не менее, регистронезависимое сравнение с использованием citext применяется эффективней, чем с применением lower.
  • Тип citext малополезен в ситуациях, когда требуется сравнивать данные без учета регистра в одних контекстах, и с учетом регистра — в других. Когда регистронезависимое сравнение требуется относительно редко, скорее используют text и вручную вызывают функцию lower. В случаях, когда чаще требуется регистронезависимое сравнение, имеет смысл сохранить данные в столбце типа citext и приводить их к типу text для регитрозависимого сравнения. Для того, чтобы в обоих случаях поиск был быстрым, потребуются два индекса.
  • Содержащая операторы citext схема должна находиться в текущем пути search_path (обычно это схема public), в противном случае будут вызываться регистрозависимые операторы для типа text.
  • Рекомендуется учитывать преобразование регистра (case mapping) и выравнивание регистра (case folding). Например, в случаях, когда одной букве в верхнем регистре соответствуют две буквы в нижнем регистре, вместо citext используются недетерминированные правила сортировки.

Установка

При наличии прав администратора СУБД включение модуля возможно выполнить вручную:

CREATE EXTENSION citext SCHEMA ext;

Настройка

Настройка не требуется.

Использование модуля

Пример использования:

CREATE TABLE users (
nick CITEXT PRIMARY KEY,
pass TEXT NOT NULL
);

INSERT INTO users VALUES ( 'larry', sha256(random()::text::bytea) );
INSERT INTO users VALUES ( 'Tom', sha256(random()::text::bytea) );
INSERT INTO users VALUES ( 'Damian', sha256(random()::text::bytea) );
INSERT INTO users VALUES ( 'NEAL', sha256(random()::text::bytea) );
INSERT INTO users VALUES ( 'Bjørn', sha256(random()::text::bytea) );

Выборка данных по условию:

SELECT * FROM users WHERE nick = 'Larry';

Оператор SELECT вернет один кортеж, несмотря на то, что в столбец nick записано значение larry, а в запросе фигурирует Larry:

 nick  |                                pass                                
-------+--------------------------------------------------------------------
larry | \x303a9ace5a8c75b2f528794477d183d0f59a4969e1fca8e332254ed3cea15ad9
(1 row)

Ссылки на документацию разработчика

Исходная документация PosgreSQL модуль citext: https://www.postgresql.org/docs/15/citext.html