Строковые литералы и escape-символы в postgresql


113

Попытка вставить escape-символ в таблицу приводит к предупреждению.

Например:

create table EscapeTest (text varchar(50));

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

Выдает предупреждение:

WARNING:  nonstandard use of escape in a string literal

( Используя PSQL 8.2 )

Кто-нибудь знает, как это обойти?

Ответы:


131

Частично. Текст вставлен, но предупреждение все равно генерируется.

Я нашел обсуждение, в котором указывалось, что перед текстом должна стоять буква "E" как таковая:

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

Это подавило предупреждение, но текст по-прежнему не возвращался правильно. Когда я добавил дополнительную косую черту, как предложил Майкл, это сработало.

В качестве таких:

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

5
Обратите внимание, что в PostgreSQL 9.0 E'testing \\ x20double-slash 'будет оцениваться как' testing \\ x20double-slash ', поэтому для литералов стиля E'string работает только подход с одинарной косой чертой
Александр

2
Для PostgreSQL 9.2 см .: postgresql.org/docs/9.2/interactive/…
Pitt

psql \copyпримечание: я обнаружил, что это E'\n'было записано в файл '\n'не как символ новой строки, когда я использовал его в аргументе запроса мета-команды psql `\ copy '.
Stew

40

Прохладно.

Я также нашел документацию по E:

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

PostgreSQL также принимает строковые константы «escape», которые являются расширением стандарта SQL. Константа escape-строки задается записью буквы E (в верхнем или нижнем регистре) непосредственно перед открывающей одинарной кавычкой, например E'foo '. (При продолжении константы escape-строки между строками, пишите E только перед первой открывающей кавычкой.) Внутри escape-строки символ обратной косой черты (\) начинает escape-последовательность, подобную C, в которой комбинация обратной косой черты и следующего символа ( s) представляет собой особое значение байта. \ b - это возврат, \ f - это подача формы, \ n - это новая строка, \ r - это возврат каретки, \ t - это табуляция. Также поддерживаются \ digits, где цифры представляют восьмеричное значение байта, и \ xhexdigits, где hexdigits представляет собой шестнадцатеричное значение байта. (Вы несете ответственность за то, чтобы создаваемые вами последовательности байтов были допустимыми символами в кодировке набора символов сервера.) Любой другой символ, следующий за обратной косой чертой, воспринимается буквально. Таким образом, чтобы включить обратную косую черту, напишите две обратной косой черты (\\). Кроме того, в escape-строку можно включить одинарную кавычку, написав \ 'в дополнение к обычному способу' '.


6

Предупреждение выдается, поскольку вы используете обратную косую черту в своих строках. Если вы хотите избежать этого сообщения, введите команду «set standard_conforming_strings = on;». Затем используйте "E" перед строкой, включая обратную косую черту, которую postgresql должен интерпретировать.


1
На самом деле, нет. Если у меня есть standard_conforming_strings = on и я запускаю команду \copy xxxxxxxxxxx FROM /support01/db/data/xxxxxxxxx_7F.txt DELIMITER AS E'\x7f', я получаю parse error at "'\x7f'". Если у меня есть standard_conforming_strings = off; и используйте ту же команду, указанную выше, без E и кавычек ... (DELIMITER AS \ x7f) Я получаю предупреждающее сообщение, но данные загружаются нормально. Так что ваше утверждение может быть правильным, но не в этом случае.

Я имел в виду строки в операторах SQL, а сейчас вы используете команду psql. Вы получаете ту же ошибку, используя команду COPY вместо \ copy?
eppesuig

1
Это правильный ответ. Современные версии PG теперь по умолчанию включены.
jpmc26 03

3

Я считаю крайне маловероятным, что Postgres усечет ваши данные при вводе - он либо отклоняет их, либо сохраняет как есть.

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=>

Пожалуйста, попробуйте тестовый пример, который я дал, и вы убедитесь в этом сами.
rjohnston,

Интересно, похоже, тогда проблема была в драйвере JDBC, потому что текст, выходящий из базы данных, определенно
усекался

3
Postgres делает усечь данные на входе в некоторых очень специфических ситуациях. Например, character varying(4)столбец с вводом «test» (два пробела после слова, 6 символов) обрезает пробелы и сохранит значение «test». Однако, как правило, вы можете предположить, что Postgres скорее ошибется, чем усечет ваши данные.
Bryson

0

Действительно глупый вопрос: вы уверены, что строка усекается, а не просто прерывается в указанном вами переносе строки (и, возможно, не отображается в вашем интерфейсе)? То есть, вы ожидаете, что поле будет отображаться как

Это будет вставлено \ n Это не будет

или

Это будет вставлено

Этого не будет

Кроме того, какой интерфейс вы используете? Возможно ли, что что-то попутно съедает вашу обратную косую черту?


1
это случилось со мной. Текст вставлялся в текстовое поле, просматривался источник, и, конечно же, была цитата, и весь текст присутствовал, просто не виден
Робертхуттингер
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.