Вставить текст с одинарными кавычками в PostgreSQL

242

У меня есть таблица test(id,name).

Мне нужно вставить такие значения, как: user log, 'my user', customer's.

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

Я получаю сообщение об ошибке, если я запускаю любое из приведенных выше инструкций.

Если есть способ сделать это правильно, поделитесь. Я не хочу никаких подготовленных заявлений.

Возможно ли использование механизма экранирования sql?

  • 1
    Используйте любое значение, выходящее за пределы вашей клиентской библиотеки. Для получения дополнительной информации вам нужно будет указать способ доступа к базе данных.
  • 0
    Доступ к базе данных @Richard Huxton осуществляется через Java.
Показать ещё 3 комментария
Теги:
special-characters
insert
quotes

6 ответов

521
Лучший ответ

Сбрасывание одиночных кавычек ' удвоением их → '' является стандартным способом и, конечно же, работает.

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

В старых версиях или если вы все еще выполняете standard_conforming_strings = off или, как правило, если вы добавили строку в E чтобы объявить синтаксис строки escape-кода Posix, вы также можете сбежать с обратным слэшем \:

E'user\ log'

Но это вообще не предпочтительнее.
Если вам приходится иметь дело со многими одинарными кавычками или несколькими слоями экранирования, вы можете избежать цитирования ада в PostgreSQL со строками, закодированными в долларах:

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

Чтобы избежать путаницы между долларовыми котировками, добавьте уникальный токен каждой паре:

$token$escape ' with ''$token$

Который может быть вложен в любое количество уровней:

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

Обратите внимание, если символ $ должен иметь особое значение в вашем клиентском программном обеспечении. Возможно, вам придется избежать этого. Это не относится к стандартным клиентам PostgreSQL, таким как psql или pgAdmin.

Это очень полезно для написания функций plpgsql или специальных команд SQL. Он не может облегчить необходимость использования подготовленных операторов или какого-либо другого метода для защиты от SQL-инъекции в вашем приложении, когда пользовательский ввод возможен. Ответ @Craig имеет больше об этом. Подробнее:

  • 1
    $ token $ работал для меня, спасибо
  • 1
    Стоит также отметить, что в некоторых версиях PgJDBC есть проблемы с кавычками в долларах - в частности, он может не игнорировать оператор-терминатор (;) внутри строк в кавычках.
Показать ещё 3 комментария
40

Это так много миров плохого, потому что ваш вопрос подразумевает, что у вас, вероятно, есть зияющие дыры SQL injection в вашем приложении.

Вы должны использовать параметризованные операторы. Для Java используйте PreparedStatement с заполнителями. Вы говорите, что не хотите использовать параметризованные утверждения, но вы не объясняете, почему, и, откровенно говоря, это очень хорошая причина не использовать их, потому что они самый простой и безопасный способ исправить проблему, которую вы пытаетесь решить.

См. Предотвращение внедрения SQL в Java. Не будьте Бобби следующей жертвой.

В PgJDBC нет публичной функции для строкового цитирования и экранирования. Это отчасти потому, что это может показаться хорошей идеей.

В PostgreSQL есть встроенные функции кавычек quote_literal и quote_ident, но они предназначены для PL/PgSQL функций, которые используют EXECUTE. В наши дни quote_literal в основном устаревает EXECUTE ... USING, что является параметризованной версией, потому что это безопаснее и проще. Вы не можете использовать их для объяснения здесь, потому что это серверные функции.


Представьте, что произойдет, если вы получите значение ');DROP SCHEMA public;-- от злоумышленника. Вы будете производить:

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

который разбивается на два оператора и комментарий, который игнорируется:

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

У вас есть база данных.

  • 0
    Я бы предпочел согласиться с одним исключением - предложения «где» (хотя он говорит «вставить») со списком значений как часть предложения «in» (или группы «или»). Я полагаю, что вы можете посчитать размер списка и сгенерировать текст для подготовленного оператора с предложением «in», но в этом случае это становится странным.
  • 0
    @Roboprog С некоторыми клиентскими драйверами вы можете использовать = ANY(?) И параметр массива.
Показать ещё 1 комментарий
15

Согласно Документация PostgreSQL (4.1.2.1. Строковые константы):

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

См. также параметр standard_conforming_strings, который контролирует, работает ли экранирование с помощью обратных косых черт.

  • 0
    спасибо за ответ, но я должен вручную экранировать каждый символ с помощью этого, если они существуют какие-либо встроенные функции для этого?
  • 3
    @MAHI Если бы существовала такая функция, она была бы в PgJDBC, а не в самом PostgreSQL, потому что экранирование должно выполняться на стороне клиента. Нет такой документированной публичной функции, потому что это ужасная идея. Вы должны использовать параметризованные операторы, поэтому вам не нужно делать какие-либо потенциально ненадежные экранированные символы.
6

В postgresql, если вы хотите вставить в него значения с ', то для этого вам нужно предоставить дополнительные '

 insert into test values (1,'user' log');
 insert into test values (2,'''my users''');
 insert into test values (3,'customer''s');
  • 13
    Это только повторение того, что уже дано другими ответами.
3

вы можете использовать функцию postrgesql chr (int):

insert into test values (2,'|| chr(39)||'my users'||chr(39)||');
1

Если вам нужно выполнить работу внутри Pg:

to_json(value)

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

  • 0
    Как этот вопрос связан с JSON?
  • 1
    @ErwinBrandstetter, извините, я могу быть выключен .. но он избегает кавычек в строках
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню