64 votes

Comment écrire une requête insensible à la casse à la fois pour MySQL et Postgres ?

J'utilise une base de données MySQL en local pour le développement, mais je la déploie sur Heroku qui utilise Postgres. Heroku gère presque tout, mais mes instructions Like insensibles à la casse deviennent sensibles à la casse. Je pourrais utiliser des instructions iLike, mais ma base de données MySQL locale ne peut pas les gérer.

Quelle est la meilleure façon d'écrire une requête insensible à la casse qui soit compatible à la fois avec MySQL et Postgres ? Ou dois-je écrire des instructions Like et iLike distinctes en fonction de la base de données à laquelle mon application s'adresse ?

73voto

MarkR Points 37178

La morale de cette histoire est la suivante : N'utilisez pas une pile logicielle différente pour le développement et la production. Jamais.

Vous vous retrouverez avec des bogues que vous ne pourrez pas reproduire en développement ; vos tests n'auront aucune valeur. Ne le faites pas.

L'utilisation d'un moteur de base de données différent est hors de question - il y aura BEAUCOUP plus de cas où il se comportera différemment que le simple LIKE (de plus, avez-vous vérifié les collations utilisées par les bases de données ? Sont-elles identiques dans TOUS les cas ? Si ce n'est pas le cas, vous pouvez oublier que ORDER BY sur les colonnes varchar fonctionne de la même manière).

58voto

Paul Tomblin Points 83687
select * from foo where upper(bar) = upper(?);

Si vous mettez le paramètre en majuscule dans l'appelant, vous pouvez éviter le deuxième appel de fonction.

36voto

jswanner Points 581

Utilisez Arel :

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

matches utilisera le ILIKE pour Postgres, et LIKE pour tout le reste.

13voto

Adam Pierce Points 12801

Dans postgres, vous pouvez faire cela :

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

Je ne suis pas sûr qu'il y ait un équivalent pour MySQL mais vous pouvez toujours faire ceci qui est un peu laid mais devrait fonctionner à la fois avec MySQL et postgres :

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

8voto

tims Points 33

Il existe plusieurs réponses, dont aucune n'est très satisfaisante.

  • LOWER(bar) = LOWER( ?) sera travail sur MySQL et Postgres, mais est susceptible de effectuer terriblement sur MySQL : MySQL n'utilisera pas ses index à cause de la fonction LOWER. Sur Postgres, vous pouvez ajouter un index fonctionnel (sur LOWER(bar) ), mais MySQL ne le prend pas en charge.
  • MySQL (à moins que vous n'ayez configuré une option de sensibilité à la casse) collation ) fait automatiquement la correspondance insensible à la casse, et utilise ses index. ( bar = ? ).
  • Depuis votre code en dehors de la base de données, gérez bar y bar_lower où bar_lower contient le résultat de inférieur(barre) . (Cela peut être possible en utilisant des déclencheurs de base de données, également). (Voir une discussion de cette solution sur Drupal ). Cette méthode est maladroite, mais elle fonctionne de la même manière sur presque toutes les bases de données.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X