PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Comment échapper une chaîne tout en faisant correspondre le modèle dans PostgreSQL

Les caractères _ et % doivent être entre guillemets pour être mis en correspondance littéralement dans une instruction LIKE, il n'y a pas moyen de contourner cela. Le choix est de le faire côté client ou côté serveur (généralement en utilisant SQL replace(), voir ci-dessous). De plus, pour bien faire les choses à 100 % dans le cas général, il y a quelques éléments à prendre en compte.

Par défaut, le guillemet à utiliser avant _ ou % est la barre oblique inverse (\), mais il peut être modifié avec une clause ESCAPE immédiatement après la clause LIKE. Dans tous les cas, le guillemet doit être répété deux fois dans le modèle pour correspondre littéralement à un seul caractère.

Exemple :... WHERE field like 'john^%node1^^[email protected]%' ESCAPE '^' correspondrait à john%node1^[email protected] suivi de n'importe quoi.

Il y a un problème avec le choix par défaut de la barre oblique inverse :elle est déjà utilisée à d'autres fins lorsque standard_conforming_strings est désactivé (PG 9.1 l'a activé par défaut, mais les versions précédentes étant encore largement utilisées, c'est un point à considérer).

De plus, si la citation pour le caractère générique LIKE est effectuée côté client dans un scénario d'injection d'entrée utilisateur, elle vient en plus de à la chaîne de guillemets normale déjà nécessaire lors de l'entrée de l'utilisateur.

Un coup d'œil à un exemple go-pgsql indique qu'il utilise des espaces réservés de style $N pour les variables... Voici donc une tentative de l'écrire d'une manière quelque peu générique :cela fonctionne avec les chaînes standard_conforming_string ON ou OFF, utilise le remplacement côté serveur de [%_], un guillemet alternatif, citant le guillemet, et évite l'injection sql :

   db.Query("SELECT * from USERS where name like replace(replace(replace($1,'^','^^'),'%','^%'),'_','^_') ||'%' ESCAPE '^'",
     variable_user_input);