web-dev-qa-db-fra.com

Insérer du texte avec des guillemets simples dans PostgreSQL

J'ai une table test(id,name).

J'ai besoin d'insérer des valeurs comme: user's log, 'my user', customer's.

 insert into test values (1,'user's log');
 insert into test values (2,''my users'');
 insert into test values (3,'customer's');

Je reçois une erreur si je lance l'une des déclarations ci-dessus.

S'il existe une méthode pour le faire correctement, merci de le partager. Je ne veux pas de déclarations préparées.

Est-il possible d'utiliser un mécanisme d'échappement SQL?

350
MAHI

Échapper aux guillemets simples _'_ en les doublant -> _''_ est la méthode standard et fonctionne bien sûr.

_'user's log'     -- incorrect syntax (unbalanced quote)
'user''s log'_

Dans les anciennes versions ou si vous exécutiez toujours avec standard_conforming_strings = off ou, généralement, si vous préférez ajouter votre chaîne avec E pour déclarer la syntaxe de chaîne d'échappement Posix , vous pouvez également vous échapper avec la barre oblique inverse _\_:

_E'user\'s log'
_

Mais ce n'est généralement pas préférable.
Si vous devez gérer plusieurs guillemets simples ou plusieurs couches d'échappement, vous pouvez éviter de citer l'enfer dans PostgreSQL avec des chaînes cotées en dollars :

_'escape '' with '''''
$$escape ' with ''$$_

Pour éviter davantage de confusion entre les cours du dollar, ajoutez un jeton unique à chaque paire:

_$token$escape ' with ''$token$
_

Qui peut être imbriqué n'importe quel nombre de niveaux:

_$token2$Inner string: $token1$escape ' with ''$token1$ is nested$token2$
_

Faites attention si le caractère _$_ doit avoir une signification particulière dans votre logiciel client. Vous devrez peut-être y échapper en plus. Ce n'est pas le cas avec les clients PostgreSQL standard tels que psql ou pgAdmin.

Tout cela est très utile pour écrire des fonctions plpgsql ou des commandes SQL ad-hoc. Cela ne peut toutefois pas réduire le besoin d'utiliser des instructions préparées ou une autre méthode de protection contre l'injection SQL dans votre application lorsque la saisie de l'utilisateur est possible. @ Craig répond en a plus. Plus de détails:

638
Erwin Brandstetter

C’est tellement de monde de mauvais, parce que votre question implique que vous avez probablement des trous béants injection SQL dans votre application.

Vous devriez utiliser des instructions paramétrées. Pour Java, utilisez PreparedStatement avec des espaces réservés . Vous dites que vous ne voulez pas utiliser d'instructions paramétrées, mais vous n'expliquez pas pourquoi , et franchement, ce doit être une très bonne raison de ne pas les utiliser car elles sont Le moyen le plus simple et le plus sûr de résoudre le problème que vous essayez de résoudre.

Voir Prévention de l'injection SQL en Java . Ne soyez pas Bobby la prochaine victime.

Il n'y a pas de fonction publique dans PgJDBC pour les guillemets et les échappements. C'est en partie parce que cela pourrait donner l'impression que c'est une bonne idée.

Il y a des fonctions de citation intégrées quote_literal et quote_ident dans PostgreSQL, mais il s'agit de fonctions PL/PgSQL qui utilisent EXECUTE . De nos jours, quote_literal est principalement obsolète par EXECUTE ... USING, qui est la version paramétrée , car sa est plus sûre . et plus facile . Vous ne pouvez pas les utiliser aux fins que vous expliquez ici, car ce sont des fonctions côté serveur.


Imaginez ce qui se passe si vous obtenez la valeur ');DROP SCHEMA public;-- d'un utilisateur malveillant. Vous produirez:

insert into test values (1,'');DROP SCHEMA public;--');

qui se décompose en deux déclarations et un commentaire qui est ignoré:

insert into test values (1,'');
DROP SCHEMA public;
--');

Oups, voilà votre base de données.

42
Craig Ringer

Selon documentation PostgreSQL (4.1.2.1. Constantes de chaînes) :

 To include a single-quote character within a string constant, write two 
 adjacent single quotes, e.g. 'Dianne''s horse'.

Voir aussi le paramètre standard_conforming_strings , qui contrôle si l'échappement avec des barres obliques inverses fonctionne ou non.

17
Claudix

Dans postgresql, si vous souhaitez insérer des valeurs avec ', vous devez pour cela ajouter '

 insert into test values (1,'user''s log');
 insert into test values (2,'''my users''');
 insert into test values (3,'customer''s');
7
Hunter

vous pouvez utiliser la fonction postgresql chr (int):

insert into test values (2,'|| chr(39)||'my users'||chr(39)||');
5
Slava Struminski

Si vous avez besoin de faire le travail dans Pg:

to_json(value)

https://www.postgresql.org/docs/9.3/static/functions-json.html#FUNCTIONS-JSON-TABLE

2
hatenine