Literais de string e caracteres de escape no postgresql

113

A tentativa de inserir um caractere de escape em uma tabela resulta em um aviso.

Por exemplo:

create table EscapeTest (text varchar(50));

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

Produz o aviso:

WARNING:  nonstandard use of escape in a string literal

( Usando PSQL 8.2 )

Alguém sabe como contornar isso?

Rjohnston
fonte

Respostas:

131

Parcialmente. O texto é inserido, mas o aviso ainda é gerado.

Eu encontrei uma discussão que indicava que o texto precisava ser precedido de 'E', como tal:

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

Isso suprimiu o aviso, mas o texto ainda não estava sendo retornado corretamente. Quando adicionei a barra adicional como Michael sugeriu, funcionou.

Assim sendo:

insert into EscapeTest (text) values (E'This is the first part \\n And this is the second');
Rjohnston
fonte
5
Observe que no PostgreSQL 9.0 E'testing \\ x20double-slash 'será avaliado como' testando \\ x20double-slash ', portanto, apenas a abordagem de barra única funciona para literais de estilo E'string'
Alexander
2
Para PostgreSQL 9.2, consulte: postgresql.org/docs/9.2/interactive/…
Pitt
psql \copyobservação: descobri que ele E'\n'foi gravado no arquivo em '\n'vez de em uma nova linha quando o usei no argumento de consulta para o meta-comando `\ copy 'do psql.
Stew
40

Legal.

Também encontrei a documentação sobre o E:

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

O PostgreSQL também aceita constantes de string de "escape", que são uma extensão do padrão SQL. Uma constante de string de escape é especificada escrevendo a letra E (maiúscula ou minúscula) antes da aspa simples de abertura, por exemplo, E'foo '. (Ao continuar uma constante de string de escape através das linhas, escreva E somente antes da primeira citação de abertura.) Dentro de uma string de escape, um caractere de barra invertida (\) começa uma sequência de escape de barra invertida em C, na qual a combinação de barra invertida e o caractere seguinte ( s) representa um valor de byte especial. \ b é um retrocesso, \ f é uma alimentação de formulário, \ n é uma nova linha, \ r é um retorno de carro, \ t é uma guia. Também são suportados \ digits, onde digits representa um valor de byte octal, e \ xhexdigits, onde hexdigits representa um valor de byte hexadecimal. (É sua responsabilidade que as sequências de bytes que você cria sejam caracteres válidos na codificação do conjunto de caracteres do servidor.) Qualquer outro caractere após uma barra invertida é considerado literalmente. Portanto, para incluir um caractere de barra invertida, escreva duas barras invertidas (\\). Além disso, uma aspa simples pode ser incluída em uma string de escape escrevendo \ ', além da forma normal de' '.

Michael Stum
fonte
6

O aviso é emitido porque você está usando barras invertidas em suas strings. Se você quiser evitar a mensagem, digite este comando "set standard_conforming_strings = on;". Em seguida, use "E" antes de sua string incluindo barras invertidas que você deseja que o postgresql interprete.

eppesuig
fonte
1
Na verdade não. Se eu tiver standard_conforming_strings = on e executar o comando \copy xxxxxxxxxxx FROM /support01/db/data/xxxxxxxxx_7F.txt DELIMITER AS E'\x7f', eu obtenho parse error at "'\x7f'". Se eu tiver standard_conforming_strings = off; e usar o mesmo comando acima sem o E e as aspas ... (DELIMITER AS \ x7f) Recebo a mensagem de aviso, mas os dados carregam bem. Portanto, sua declaração pode estar correta, mas não neste caso.
Eu estava me referindo a strings em instruções SQL, enquanto você agora está usando um comando psql. Você obtém o mesmo erro usando o comando COPY em vez de \ copy?
eppesuig
1
Esta é a resposta certa. As versões modernas do PG agora assumem como padrão.
jpmc26
3

Acho altamente improvável que o Postgres trunque seus dados na entrada - ele os rejeita ou os armazena como estão.

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
fonte
Por favor, tente o caso de teste que dei e você verá por si mesmo.
rjohnston
Interessante, parece que o problema estava no driver JDBC, porque o texto que saía do banco de dados estava definitivamente sendo truncado ...
rjohnston
3
Postgres faz dados TRUNCATE em entrada em algumas situações muito específicas. Por exemplo, uma character varying(4)coluna com a entrada "teste" (dois espaços após a palavra, 6 caracteres) truncará os espaços e armazenará o valor "teste". Como regra geral, entretanto, você pode assumir que o Postgres irá gerar um erro em vez de truncar seus dados.
Bryson,
0

Pergunta realmente estúpida: tem certeza de que a string está sendo truncada, e não apenas quebrada na quebra de linha que você especificar (e possivelmente não está aparecendo em sua interface)? Ou seja, você espera que o campo seja mostrado como

Isso será inserido \ n Isso não será

ou

Isso será inserido

Isso não vai ser

Além disso, qual interface você está usando? É possível que algo ao longo do caminho esteja engolindo suas barras invertidas?

Comunidade
fonte
1
isso aconteceu comigo. O texto estava sendo inserido em uma caixa de texto, visualizado a fonte, e com certeza, havia uma citação e o texto inteiro estava presente, mas não visível
roberthuttinger