Как написать запрос без учета регистра как для MySQL, так и для Postgres?

StackOverflow https://stackoverflow.com/questions/203399

Вопрос

Я использую базу данных MySQL локально для разработки, но развертываю ее в Heroku, который использует Postgres.Heroku обрабатывает почти все, но мои операторы Like, нечувствительные к регистру, становятся чувствительными к регистру.Я мог бы использовать операторы iLike, но моя локальная база данных MySQL не справится с этим.

Как лучше всего написать запрос без учета регистра, совместимый как с MySQL, так и с Postgres?Или мне нужно написать отдельные операторы Like и iLike в зависимости от БД, с которой общается мое приложение?

Это было полезно?

Решение

select * from foo where upper(bar) = upper(?);

Если вы установите параметр в верхний регистр в вызывающей стороне, вы можете избежать второго вызова функции.

Другие советы

Мораль этой истории такова:Не используйте другой стек программного обеспечения для разработки и производства.Никогда.

Вы просто получите ошибки, которые не сможете воспроизвести в разработке;ваше тестирование будет бесполезным.Просто не делай этого.

Об использовании другого механизма базы данных не может быть и речи - будет НАМНОГО больше случаев, когда он будет вести себя иначе, чем просто НРАВИТСЯ (кроме того, проверяли ли вы параметры сортировки, используемые базами данных?Они идентичны в КАЖДОМ СЛУЧАЕ?Если нет, вы можете забыть ORDER BY для столбцов varchar, работающих одинаково)

Используйте Арел:

Author.where(Author.arel_table[:name].matches("%foo%"))

matches будет использовать ILIKE оператор для Postgres и LIKE для всего остального.

В postgres вы можете сделать это:

SELECT whatever FROM mytable WHERE something ILIKE 'match this';

Я не уверен, существует ли эквивалент для MySQL, но вы всегда можете сделать это, что немного некрасиво, но должно работать как в MySQL, так и в Postgres:

SELECT whatever FROM mytable WHERE UPPER(something) = UPPER('match this');

Есть несколько ответов, ни один из которых не является удовлетворительным.

  • НИЖНИЙ(бар) = НИЖНИЙ(?) воля работа на MySQL и Postgres, но, скорее всего, ужасно работать на MySQL:MySQL не будет использовать свои индексы из-за функции LOWER.В Postgres вы можете добавить функциональный индекс (на НИЖНИЙ (бар)), но MySQL этого не поддерживает.
  • MySQL будет (если вы не установили регистрозависимый сопоставление) автоматически выполняет сопоставление без учета регистра и использует его индексы.(бар = ?).
  • Из вашего кода вне базы данных поддерживайте бар и bar_lower поля, где bar_lower содержит результат нижний (бар).(Это также возможно с использованием триггеров базы данных).(См. обсуждение этого решения на Друпал).Это неуклюже, но, по крайней мере, работает одинаково практически для каждой базы данных.

REGEXP не чувствителен к регистру (если не используется с BINARY) и может использоваться следующим образом...

    SELECT id FROM person WHERE name REGEXP 'john';

...чтобы соответствовать «Джон», «ДЖОН», «Джон» и т. д.

Если вы используете PostgreSQL 8.4, вы можете использовать циттекст модуль для создания текстовых полей без учета регистра.

используйте СОРТИРОВАТЬ.

http://dev.mysql.com/doc/refman/5.0/en/case-sensitivity.html

Вы также можете рассмотреть возможность проверки логика поиска плагин, который делает НРАВИТСЯ/МНЕ НРАВИТСЯ переключатель для вас.

Вы также можете использовать ~* в postgres, если хотите сопоставить подстроку внутри блока.~ соответствует подстроке с учетом регистра, ~* подстроке без учета регистра.Это медленная операция, но, возможно, она будет полезна для поиска.

Select * from table where column ~* 'UnEvEn TeXt';
Select * from table where column ~ 'Uneven text';

Оба наступили бы на «какой -то неровный текст здесь», только первый наживет на «какой -то неровный текст здесь» здесь »

Лучше всего конвертировать в верхний формат, поскольку он охватывает совместимый синтаксис для трех наиболее часто используемых серверных частей базы данных Rails.PostgreSQL, MySQL и SQLite поддерживают этот синтаксис.У него есть (незначительный) недостаток: вам придется писать строку поиска в верхнем регистре в вашем приложении или в строке условий, что делает ее немного уродливой, но я думаю, что совместимость, которую вы получаете, того стоит.

И MySQL, и SQLite3 имеют оператор LIKE, нечувствительный к регистру.Только PostgreSQL имеет чувствительный к регистру оператор LIKE и специальный для PostgreSQL (согласно руководству) оператор ILIKE для поиска без учета регистра.Вы можете указать ILIKE вместо LIKE в ваших условиях приложения Rails, но имейте в виду, что приложение перестанет работать под MySQL или SQLite.

Третий вариант — проверить, какой механизм базы данных вы используете, и соответствующим образом изменить строку поиска.Это можно было бы лучше сделать, взломав или исправив адаптеры подключения ActiveRecord и попросив адаптер PostgreSQL изменить строку запроса, заменив «LIKE» на «ILIKE» перед выполнением запроса.Однако это решение является наиболее запутанным, и в свете более простых способов, таких как использование обоих терминов в верхнем регистре, я думаю, что это не стоит затраченных усилий (хотя вы получите много очков за это).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top