Question

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

Quel est le meilleur moyen d'écrire une requête non sensible à la casse compatible avec MySQL et Postgres? Ou dois-je écrire des instructions séparées Like et iLike en fonction de la base de données vers laquelle mon application parle?

Était-ce utile?

La solution

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

Si vous définissez le paramètre sur majuscule dans l'appelant, vous pouvez éviter le second appel de fonction.

Autres conseils

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

Vous allez juste vous retrouver avec des bugs que vous ne pouvez pas reproduire dans dev; vos tests seront sans valeur. Ne le fais pas.

Il est hors de question d'utiliser un autre moteur de base de données - il y aura beaucoup plus de cas où il se comportera différemment de LIKE (avez-vous également vérifié les classements utilisés par les bases de données? Sont-ils identiques dans TOUS LES CAS? Sinon , vous pouvez oublier ORDER BY sur les colonnes varchar fonctionnant de la même manière)

Utilisez Arel:

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

correspond utilisera l'opérateur ILIKE pour Postgres et LIKE pour tout le reste.

Dans postgres, vous pouvez faire ceci:

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

Je ne sais pas s'il existe un équivalent pour MySQL, mais vous pouvez toujours le faire, ce qui est un peu moche mais devrait fonctionner à la fois avec MySQL et postgres:

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

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

  • LOWER (bar) = LOWER (?) fonctionnera sur MySQL et Postgres, mais risque de très bien fonctionner sur MySQL : MySQL n'utilisera pas ses index à cause de la fonction LOWER. Sur Postgres, vous pouvez ajouter un index fonctionnel (sur LOWER (barre) ), mais MySQL ne la prend pas en charge.
  • MySQL le fera (à moins que vous n'ayez défini un classement sensible à la casse. faire automatiquement la correspondance insensible à la casse et utiliser ses index. ( bar =? ).
  • Dans votre code en dehors de la base de données, conservez les champs bar et bar_lower , où bar_lower contient le résultat de lower (bar) . (Cela peut être possible en utilisant des déclencheurs de base de données, également). (Voir une discussion de cette solution sur Drupal ). Ceci est maladroit, mais fonctionne au moins de la même manière sur à peu près toutes les bases de données.

REGEXP est insensible à la casse (sauf si utilisé avec BINARY), et peut être utilisé, comme si ...

    SELECT id FROM person WHERE name REGEXP 'john';

... pour correspondre à 'John', 'JOHN', 'john', etc.

Si vous utilisez PostgreSQL 8.4, vous pouvez utiliser le module citext . créer des champs de texte ne respectant pas la casse.

Vous pouvez également consulter le plug-in searchlogic , qui exécute le LIKE / ILIKE pour vous.

Vous pouvez également utiliser ~ * dans postgres si vous souhaitez faire correspondre une sous-chaîne dans un bloc. ~ correspond à la sous-chaîne sensible à la casse, ~ * sous-chaîne insensible à la casse. C’est une opération lente, mais pourrais-je la trouver utile pour les recherches?

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

Les deux cliquent sur "Un texte inégal ici". Seul le premier toucherait "Certains TEXTES INATTENDUS"

La conversion en haut est préférable car elle couvre la syntaxe compatible avec les 3 moteurs de base de données Rails les plus utilisés. PostgreSQL, MySQL et SQLite supportent tous cette syntaxe. L’inconvénient (mineur) est que vous devez mettre votre chaîne de recherche en majuscule dans votre application ou dans votre chaîne de conditions, ce qui la rend un peu plus moche, mais je pense que la compatibilité que vous obtenez en vaut la peine.

MySQL et SQLite3 ont un opérateur LIKE qui ne respecte pas la casse. Seul PostgreSQL a un opérateur LIKE sensible à la casse et un opérateur ILIKE spécifique à PostgreSQL (selon le manuel) pour les recherches ne respectant pas la casse. Vous pouvez spécifier ILIKE au lieu de LIKE dans vos conditions sur l'application Rails, mais sachez que l'application cessera de fonctionner sous MySQL ou SQLite.

Une troisième option pourrait consister à vérifier le moteur de base de données utilisé et à modifier la chaîne de recherche en conséquence. Cela pourrait être mieux fait en piratant les adaptateurs de connexion d’ActiveRecord / monkeypatching et en demandant à l’adaptateur PostgreSQL de modifier la chaîne de requête pour substituer & LIKE " pour " ILIKE " avant l'exécution de la requête. Cette solution est cependant la plus compliquée et à la lumière de façons plus simples, comme de mettre les deux termes en majuscule, je pense que ce n’est pas la peine de faire un effort (bien que vous obtiendriez beaucoup de points Brownie pour le faire de cette façon).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top