Как вы пишете нечувствительный к регистру запрос для MySQL и Postgres?

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

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

Ответ 1

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

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

Ответ 2

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

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

Использование другого механизма базы данных не может быть и речи - будет FAR больше случаев, когда он ведет себя иначе, чем просто LIKE (также вы проверили сопоставления, используемые базами данных, идентичны ли они в КАЖДОМ случае?, вы можете забыть ORDER BY на столбцах varchar, работающих одинаково)

Ответ 3

Использовать Arel:

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

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

Ответ 4

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

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

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

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

Ответ 5

Существует несколько ответов, ни одна из которых не является удовлетворительной.

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

Ответ 6

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

    SELECT id FROM person WHERE name REGEXP 'john';

... для соответствия "John", "JOHN", "john" и т.д.

Ответ 7

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

Ответ 9

Вы также можете рассмотреть возможность просмотра searchlogic плагина, который выполняет LIKE/ILIKE для вас.

Ответ 10

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

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

Оба набросились на "Some Uneven text here" Только первый бы нажал на "Some UNEVEN TEXT здесь"

Ответ 11

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

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

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