Literales de cadena y caracteres de escape en postgresql

113

Intentar insertar un carácter de escape en una tabla da como resultado una advertencia.

Por ejemplo:

create table EscapeTest (text varchar(50));

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

Produce la advertencia:

WARNING:  nonstandard use of escape in a string literal

( Usando PSQL 8.2 )

¿Alguien sabe cómo solucionar esto?

rjohnston
fuente

Respuestas:

131

Parcialmente. Se inserta el texto, pero aún se genera la advertencia.

Encontré una discusión que indicaba que el texto debía ir precedido de 'E', como tal:

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

Esto suprimió la advertencia, pero el texto aún no se devolvía correctamente. Cuando agregué la barra oblicua adicional como sugirió Michael, funcionó.

Como tal:

insert into EscapeTest (text) values (E'This is the first part \\n And this is the second');
rjohnston
fuente
5
Tenga en cuenta que en PostgreSQL 9.0 E'testing \\ x20double-slash 'se evaluará como' testing \\ x20double-slash ', por lo que solo el enfoque de barra simple funciona para los literales de estilo E'string'
Alexander
2
Para PostgreSQL 9.2, consulte: postgresql.org/docs/9.2/interactive/…
Pitt
psql \copynota: descubrí que E'\n'se escribió en el archivo en '\n'lugar de como una nueva línea cuando lo usé en el argumento de consulta del metacomando `\ copy 'de psql.
Guiso
40

Frio.

También encontré la documentación sobre la E:

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

PostgreSQL también acepta constantes de cadena de "escape", que son una extensión del estándar SQL. Una constante de cadena de escape se especifica escribiendo la letra E (mayúscula o minúscula) justo antes de la comilla simple de apertura, por ejemplo, E'foo '. (Cuando continúe una constante de cadena de escape a lo largo de las líneas, escriba E solo antes de la primera cita de apertura). Dentro de una cadena de escape, un carácter de barra invertida (\) comienza una secuencia de escape de barra invertida similar a C, en la que la combinación de barra invertida y el siguiente carácter ( s) representa un valor de byte especial. \ b es un retroceso, \ f es un formulario de alimentación, \ n es una nueva línea, \ r es un retorno de carro, \ t es una pestaña. También se admiten \ dígitos, donde los dígitos representan un valor de byte octal, y \ xhexdigits, donde hexdigits representa un valor de byte hexadecimal. (Es su responsabilidad que las secuencias de bytes que cree sean caracteres válidos en la codificación del juego de caracteres del servidor). Cualquier otro carácter que siga a una barra invertida se toma literalmente. Por lo tanto, para incluir un carácter de barra invertida, escriba dos barras invertidas (\\). Además, se puede incluir una comilla simple en una cadena de escape escribiendo \ ', además de la forma normal de' '.

Michael Stum
fuente
6

La advertencia se emite porque está utilizando barras invertidas en sus cadenas. Si desea evitar el mensaje, escriba este comando "set standard_conforming_strings = on;". Luego use "E" antes de su cadena, incluidas las barras invertidas que desea que postgresql interprete.

eppesuig
fuente
1
Realmente no. Si tengo standard_conforming_strings = activado y ejecuto el comando \copy xxxxxxxxxxx FROM /support01/db/data/xxxxxxxxx_7F.txt DELIMITER AS E'\x7f', obtengo parse error at "'\x7f'". Si tengo el standard_conforming_strings = off; y use el mismo comando anterior sin la E y las Comillas ... (DELIMITER AS \ x7f) Recibo el mensaje de advertencia, pero los datos se cargan bien. Entonces, su declaración puede ser correcta, pero no en este caso.
Me refería a cadenas en declaraciones SQL, mientras que ahora está usando un comando psql. ¿Obtiene el mismo error al usar el comando COPY en lugar de \ copy?
eppesuig
1
Esta es la respuesta correcta. Las versiones modernas de PG ahora lo tienen por defecto.
jpmc26
3

Me parece muy poco probable que Postgres trunque sus datos en la entrada, ya sea que los rechace o los almacene como están.

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
fuente
Pruebe el caso de prueba que le di y lo verá por sí mismo.
rjohnston
Interesante, parece que el problema estaba en el controlador JDBC entonces, porque el texto que salía de la base de datos definitivamente estaba truncado ...
rjohnston
3
Postgres hace los datos truncados en la entrada en algunas situaciones muy específicas. Por ejemplo, una character varying(4)columna con la entrada "prueba" (dos espacios después de la palabra, 6 caracteres) truncará los espacios y almacenará el valor "prueba". Sin embargo, como regla general, puede asumir que Postgres producirá un error en lugar de truncar sus datos.
Bryson
0

Pregunta realmente estúpida: ¿está seguro de que la cadena se está truncando y no solo se rompe en el salto de línea que especifica (y posiblemente no se muestra en su interfaz)? Es decir, ¿espera que el campo se muestre como

Esto se insertará \ n Esto no se

o

Esto se insertará

Esto no sera

Además, ¿qué interfaz estás usando? ¿Es posible que algo en el camino te esté comiendo las barras invertidas?

Comunidad
fuente
1
esto me pasó a mí. El texto se estaba insertando en un cuadro de texto, se vio la fuente y,
efectivamente