PostgreSQL: как сделать запрос без учета регистра

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

SELECT id FROM groups where name='administrator'

SELECT id FROM groups where name='ADMINISTRATOR'

SELECT id FROM groups where name='Administrator'

Ответ 1

Используйте LOWER для преобразования строк в нижний регистр перед сравнением.

Попробуйте следующее:

SELECT id 
  FROM groups
 WHERE LOWER(name)=LOWER('Administrator')

Ответ 2

используя ILIKE вместо LIKE

SELECT id FROM groups WHERE name ILIKE 'Administrator'

Ответ 3

Наиболее распространенным подходом является либо строчная, либо прописная строка поиска и данные. Но есть две проблемы.

  • Он работает на английском языке, но не на всех языках. (Возможно, даже в большинство языков.) Не каждая строчная буква имеет соответствующий Прописная буква; не каждая буква верхнего регистра имеет соответствующую строчная буква.
  • Использование таких функций, как lower() и upper(), даст вам последовательность сканирования. Он не может использовать индексы. В моей тестовой системе использование lower() принимает примерно в 2000 раз больше, чем запрос, который может использовать индекс. (Тестовые данные имеют чуть более 100 тыс. Строк.)

Есть, по крайней мере, три менее часто используемых решения, которые могут быть более эффективными.

  • Используйте модуль citext, который в основном имитирует поведение типа данных, не учитывающих регистр. Загрузив этот модуль, вы можете создать индекс без учета регистра на CREATE INDEX ON groups (name::citext);. (Но см. Ниже.)
  • Используйте регистр без учета регистра. Это устанавливается при инициализации база данных. Использование без учета регистра соответствия означает, что вы можете принять почти любой формат из клиентского кода, и вы все равно вернетесь полезные результаты. (Это также означает, что вы не можете делать запросы с учетом регистра. Duh.)
  • Создайте функциональный индекс. Создайте индекс нижнего регистра, используя CREATE INDEX ON groups (LOWER(name));. Сделав это, вы можете воспользоваться индекса с запросами типа SELECT id FROM groups WHERE LOWER(name) = LOWER('ADMINISTRATOR'); или SELECT id FROM groups WHERE LOWER(name) = 'administrator'; Однако вы должны помнить, что используете LOWER().

Модуль citext не обеспечивает истинный тип данных, нечувствительных к регистру. Вместо этого он ведет себя так, как если бы каждая строка была нижней. То есть, он ведет себя так, как будто вы вызывали lower() для каждой строки, как в номере 3 выше. Преимущество состоит в том, что программистам не нужно запоминать строчные строки. Но вам нужно прочитать разделы "Поведение сравнения строк" ​​и "Ограничения" в документах, прежде чем вы решите использовать citext.

Ответ 4

Вы можете использовать ILIKE. то есть.

SELECT id FROM groups where name ILIKE 'administrator'

Ответ 5

Вы также можете прочитать ключевое слово ILIKE. Иногда это может быть весьма полезно, хотя оно не соответствует стандарту SQL. См. Здесь для получения дополнительной информации: http://www.postgresql.org/docs/9.2/static/functions-matching.html

Ответ 6

Вы также можете использовать регулярные выражения POSIX, например

SELECT id FROM groups where name ~* 'administrator'

SELECT 'asd' ~* 'AsD' возвращает t

Ответ 7

Использование ~* может значительно улучшить производительность, с функциональностью INSTR.

SELECT id FROM groups WHERE name ~* 'adm'

возвращать строки с именем, содержащим OR, равным "adm".