Littéraux de chaîne et caractères d'échappement dans postgresql

113

Tenter d'insérer un caractère d'échappement dans une table entraîne un avertissement.

Par exemple:

create table EscapeTest (text varchar(50));

insert into EscapeTest (text) values ('This is the first part \n And this is the second');

Produit l'avertissement:

WARNING:  nonstandard use of escape in a string literal

( Utilisation de PSQL 8.2 )

Quelqu'un sait comment contourner cela?

rjohnston
la source

Réponses:

131

Partiellement. Le texte est inséré, mais l'avertissement est toujours généré.

J'ai trouvé une discussion qui indiquait que le texte devait être précédé d'un `` E '', en tant que tel:

insert into EscapeTest (text) values (E'This is the first part \n And this is the second');

Cela a supprimé l'avertissement, mais le texte n'était toujours pas renvoyé correctement. Quand j'ai ajouté la barre oblique supplémentaire comme Michael l'a suggéré, cela a fonctionné.

En tant que tel:

insert into EscapeTest (text) values (E'This is the first part \\n And this is the second');
rjohnston
la source
5
Notez que sur PostgreSQL 9.0, E'testing \\ x20double-slash 'sera évalué comme' testing \\ x20double-slash ', donc seule l'approche à une seule barre oblique fonctionne pour les littéraux de style E'string'
Alexander
2
Pour PostgreSQL 9.2, voir: postgresql.org/docs/9.2/interactive/…
Pitt
psql \copyRemarque: j'ai trouvé que cela E'\n'était écrit dans un fichier '\n'plutôt que comme une nouvelle ligne lorsque je l'ai utilisé dans l'argument de requête de la méta-commande `\ copy 'de psql.
Ragoût du
40

Cool.

J'ai également trouvé la documentation concernant le E:

http://www.postgresql.org/docs/8.3/interactive/sql-syntax-lexical.html#SQL-SYNTAX-STRINGS

PostgreSQL accepte également les constantes de chaîne "d'échappement", qui sont une extension du standard SQL. Une constante de chaîne d'échappement est spécifiée en écrivant la lettre E (majuscule ou minuscule) juste avant le guillemet simple d'ouverture, par exemple E'foo '. (Lorsque vous continuez une constante de chaîne d'échappement sur plusieurs lignes, écrivez E uniquement avant le premier guillemet d'ouverture.) Dans une chaîne d'échappement, une barre oblique inverse (\) commence une séquence d'échappement de type barre oblique inverse de type C, dans laquelle la combinaison d'une barre oblique inverse et du caractère suivant ( s) représente une valeur d'octet spéciale. \ b est un retour arrière, \ f est un saut de page, \ n est une nouvelle ligne, \ r est un retour chariot, \ t est une tabulation. Sont également pris en charge \ digits, où digits représente une valeur d'octet octal, et \ xhexdigits, où hexdigits représente une valeur d'octet hexadécimal. (Il est de votre responsabilité que les séquences d'octets que vous créez soient des caractères valides dans le codage du jeu de caractères du serveur.) Tout autre caractère suivant une barre oblique inverse est pris à la lettre. Ainsi, pour inclure une barre oblique inverse, écrivez deux barres obliques inverses (\\). De plus, un guillemet simple peut être inclus dans une chaîne d'échappement en écrivant \ ', en plus de la manière normale de' '.

Michael Stum
la source
6

L'avertissement est émis car vous utilisez des barres obliques inverses dans vos chaînes. Si vous voulez éviter le message, tapez cette commande "set standard_conforming_strings = on;". Ensuite, utilisez "E" avant votre chaîne, y compris les barres obliques inverses que vous voulez que postgresql interprète.

eppesuig
la source
1
Pas vraiment. Si j'ai standard_conforming_strings = on et exécutez la commande \copy xxxxxxxxxxx FROM /support01/db/data/xxxxxxxxx_7F.txt DELIMITER AS E'\x7f', j'obtiens parse error at "'\x7f'". Si j'ai le standard_conforming_strings = off; et utilisez la même commande ci-dessus sans le E et les citations ... (DELIMITER AS \ x7f) Je reçois le message d'avertissement, mais les données se chargent bien. Votre déclaration peut donc être correcte, mais pas dans ce cas.
Je faisais référence aux chaînes dans les instructions SQL, alors que vous utilisez maintenant une commande psql. Obtenez-vous la même erreur en utilisant la commande COPY au lieu de \ copy?
eppesuig
1
C'est la bonne réponse. Les versions modernes de PG sont désormais activées par défaut.
jpmc26
3

Je trouve qu'il est très peu probable que Postgres tronque vos données en entrée - il les rejette ou les stocke telles quelles.

milen@dev:~$ psql
Welcome to psql 8.2.7, the PostgreSQL interactive terminal.

Type:  \copyright for distribution terms
       \h for help with SQL commands
       \? for help with psql commands
       \g or terminate with semicolon to execute query
       \q to quit

milen=> create table EscapeTest (text varchar(50));
CREATE TABLE
milen=> insert into EscapeTest (text) values ('This will be inserted \n This will not be');
WARNING:  nonstandard use of escape in a string literal
LINE 1: insert into EscapeTest (text) values ('This will be inserted...
                                              ^
HINT:  Use the escape string syntax for escapes, e.g., E'\r\n'.
INSERT 0 1
milen=> select * from EscapeTest;
          text
------------------------
 This will be inserted
  This will not be
(1 row)

milen=>
Milen A. Radev
la source
Veuillez essayer le cas de test que j'ai donné et vous le verrez par vous-même.
rjohnston le
Intéressant, on dirait que le problème était dans le pilote JDBC à l'époque, car le texte sortant de la base de données était très certainement tronqué ...
rjohnston
3
Postgres fait des données tronquées sur l' entrée dans certaines situations très spécifiques. Par exemple, une character varying(4)colonne avec l'entrée "test" (deux espaces après le mot, 6 caractères) tronquera les espaces et stockera la valeur "test". En règle générale, cependant, vous pouvez supposer que Postgres fera une erreur plutôt que de tronquer vos données.
Bryson
0

Question vraiment stupide: êtes-vous sûr que la chaîne est tronquée, et pas seulement interrompue au saut de ligne que vous spécifiez (et peut-être ne pas s'afficher dans votre interface)? Par exemple, vous attendez-vous à ce que le champ apparaisse comme

Cela sera inséré \ n Ce ne sera pas

ou

Ce sera inséré

Ce ne sera pas

De plus, quelle interface utilisez-vous? Est-il possible que quelque chose en cours de route mange vos barres obliques inverses?

Communauté
la source
1
cela m'est arrivé. Le texte était inséré dans une zone de texte, vu la source, et bien sûr, il y avait une citation et le texte entier était présent, mais pas visible
roberthuttinger