Jak napisać zapytanie o wielkość liter zarówno dla MySQL jak i Postgres?

Uruchamiam lokalnie bazę danych MySQL do rozwoju, ale wdrażam do Heroku, który używa Postgres. Heroku radzi sobie prawie ze wszystkim, ale moje wypowiedzi są niewrażliwe na wielkość liter. Przydałyby mi się instrukcje iLike, ale moja lokalna baza danych MySQL sobie z tym nie poradzi.

Jaki jest najlepszy sposób na napisanie zapytania bez rozróżniania wielkości liter, które jest kompatybilne zarówno z MySQL jak i Postgres? Czy muszę pisać oddzielne jak i lubię wypowiedzi w zależności od DB moja aplikacja mówi do?

Author: cHao, 2008-10-15

11 answers

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

Jeśli ustawisz parametr na wielkie litery w wywołującym, możesz uniknąć drugiego wywołania funkcji.

 58
Author: Paul Tomblin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-17 00:37:23

Morał tej historii jest taki: nie używaj innego stosu oprogramowania do rozwoju i produkcji. Nigdy.

Po prostu skończysz z błędami, których nie możesz odtworzyć w dev-ie; twoje testy będą bezwartościowe. Po prostu tego nie rób.

Używanie innego silnika bazodanowego nie wchodzi w grę - będzie znacznie więcej przypadków, w których zachowuje się on inaczej niż tak po prostu (również, sprawdziłeś kolacje używane przez bazy danych? Czy są identyczne w każdym przypadku? Jeśli nie, możesz zapomnieć ORDER BY on VARCHAR columns working the same)

 74
Author: MarkR,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-11 14:47:06

Użyj Arel:

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

matches użyje operatora ILIKE dla Postgres i LIKE dla wszystkiego innego.

 36
Author: jswanner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-13 23:15:00

W postgres można to zrobić:

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

Nie jestem pewien, czy istnieje odpowiednik dla MySQL, ale zawsze można to zrobić, co jest trochę brzydkie, ale powinno działać zarówno w MySQL i postgres:

SELECT whatever FROM mytable WHERE UPPER(something) = UPPER('match this');
 13
Author: Adam Pierce,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-15 01:32:37

Jest kilka odpowiedzi, z których żadna nie jest bardzo zadowalająca.

  • LOWER (bar) = LOWER (?) będzie działać na MySQL i Postgres, ale prawdopodobnie będzie działać okropnie na MySQL: MySQL nie będzie używać swoich indeksów z powodu niższej funkcji. Na Postgres można dodać indeks funkcjonalny (na LOWER (bar) ), ale MySQL tego nie obsługuje.
  • MySQL będzie (chyba że ustawisz rozróżnianie wielkości liter collation) dopasowywać wielkość liter automatycznie i użyj jego indeksów. ( bar = ?).
  • z kodu spoza bazy danych utrzymuj pola bari bar_lower, gdzie bar_lower zawiera wynik lower(bar). (Może to być możliwe również przy użyciu wyzwalaczy bazy danych). (Zobacz omówienie tego rozwiązania na Drupal ). Jest to niezdarne, ale przynajmniej działa tak samo w prawie każdej bazie danych.
 8
Author: tims,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-20 12:14:25

Wyrażenie REGEXP jest niewrażliwe na wielkość liter (chyba że jest używane z binarnym) i może być używane w ten sposób...

    SELECT id FROM person WHERE name REGEXP 'john';

...aby dopasować 'John',' JOHN',' john', itp.

 5
Author: Ben Wilhelm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-31 22:30:01

Jeśli używasz PostgreSQL 8.4, możesz użyć modułu citext do tworzenia pól tekstowych bez rozróżniania wielkości liter.

 2
Author: MkV,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-05 16:19:33
 2
Author: RuelB,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-27 15:37:46

Możesz również rozważyć sprawdzenie wtyczki searchlogic, która wykonuje dla ciebie przełącznik LIKE/ILIKE.

 1
Author: Trevor Turk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-11 14:41:45

Możesz również użyć ~* w postgres, jeśli chcesz dopasować podłańcuch w bloku. ~ dopasowuje wielkość podciągu, ~ * wielkość podciągu. To powolne działanie, ale może Uznam to za przydatne do wyszukiwania.

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

Oba trafiłyby na " jakiś nierówny tekst tutaj" Tylko ten pierwszy trafiłby na "jakiś nierówny tekst tutaj"

 1
Author: Sheldon Ross,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-12 00:59:18

Konwersja na upper jest najlepsza, ponieważ obejmuje kompatybilną składnię 3 najczęściej używanych baz danych Rails. Wszystkie PostgreSQL, MySQL i SQLite wspierają tę składnię. Ma (drobną) wadę, że trzeba wielkie litery szukanego ciągu w aplikacji lub w łańcuchu warunków, co czyni go nieco brzydszym, ale myślę, że kompatybilność, którą zyskujesz, sprawia, że warto.

Zarówno MySQL, jak i sqlite3 mają Operator niewrażliwy na wielkość liter. Tylko PostgreSQL ma Operator uwzględniający wielkość liter i specyficzny dla PostgreSQL (zgodnie z instrukcją) operator ILIKE do wyszukiwania bez rozróżniania wielkości liter. Możesz określić ILIKE insead of LIKE w Twoich warunkach na aplikacji Rails, ale pamiętaj, że aplikacja przestanie działać pod MySQL lub SQLite.

Trzecią opcją może być sprawdzenie, którego silnika bazy danych używasz i odpowiednio zmodyfikować szukany ciąg. Można to zrobić lepiej włamując się do / monkeypatching adapterów połączeniowych ActiveRecord i mając adapter PostgreSQL zmodyfikuj łańcuch zapytania, aby zastąpić "LIKE " przez" ILIKE " przed wykonaniem zapytania. To rozwiązanie jest jednak najbardziej zawiłe i w świetle łatwiejszych sposobów, takich jak uppercasing obu terminów, myślę, że nie jest to wysiłek worh (choć można dostać mnóstwo punktów brownie za robienie tego w ten sposób).

 0
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-05 18:19:05