594

我有一张桌子test(id,name)

我需要插入如下值: user's log, 'my user', customer's.

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

如果我运行上述任何语句,我会收到错误消息。

如果有任何方法可以正确地做到这一点,请分享。我不想要任何准备好的陈述。

是否可以使用 sql 转义机制?

4

7 回答 7

1022

字符串文字

'通过将单引号加倍来转义单引号->''是标准方式,当然也可以:

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

请注意,普通单引号(ASCII / UTF-8 代码 39)不是反引号`,它在 Postgres 中没有特殊用途(与某些其他 RDBMS 不同),而不是双引号",用于标识符。

在旧版本中,或者如果您仍在运行,standard_conforming_strings = off或者,通常,如果您在字符串前面加上E声明Posix 转义字符串语法,您也可以使用反斜杠进行转义\

E'user\'s log'

反斜杠本身用另一个反斜杠转义。但这通常不是可取的。
如果您必须处理许多单引号或多层转义,您可以避免在 PostgreSQL 中用美元引用的字符串引用地狱:

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

为了进一步避免美元报价之间的混淆,请为每一对添加一个唯一的标记:

$token$escape ' with ''$token$

可以嵌套任意数量的级别:

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

请注意该$字符在您的客户端软件中是否应具有特殊含义。此外,您可能还必须逃避它。对于像 psql 或 pgAdmin 这样的标准 PostgreSQL 客户端,情况并非如此。

这对于编写 plpgsql 函数或 ad-hoc SQL 命令非常有用。但是,当用户可以输入时,它不能减轻使用准备好的语句或其他方法来防止应用程序中的 SQL 注入的需要。@Craig 的回答对此有更多了解。更多细节:

Postgres 中的值

在处理数据库中的值时,有几个有用的函数可以正确引用字符串:

于 2012-09-07T15:06:16.447 回答
51

这是一个糟糕的世界,因为您的问题暗示您的应用程序中可能存在巨大的SQL 注入漏洞。

您应该使用参数化语句。对于 Java,PreparedStatement与占位符一起使用。您说您不想使用参数化语句,但您没有解释原因,坦率地说,不使用它们必须是一个很好的理由,因为它们是解决您正在尝试的问题的最简单、最安全的方法解决。

请参阅防止 Java 中的 SQL 注入。不要成为鲍比的下一个受害者。

PgJDBC 中没有用于字符串引用和转义的公共函数。这部分是因为它可能使它看起来像是一个好主意。

在 PostgreSQL中有内置的引用函数quote_literalquote_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;
--');

哎呀,你的数据库到了。

于 2012-09-07T11:36:45.183 回答
46

根据PostgreSQL 文档(4.1.2.1。字符串常量)

要在字符串常量中包含单引号字符,请写入两个相邻的单引号,例如'Dianne''s horse'。

另请参阅standard_conforming_strings参数,该参数控制是否使用反斜杠进行转义。

于 2012-09-07T11:23:33.580 回答
31

在 postgresql 中,如果您想在其中插入值,'那么为此您必须提供额外的'

 insert into test values (1,'user''s log');
 insert into test values (2,'''my users''');
 insert into test values (3,'customer''s');
于 2012-09-07T20:44:21.213 回答
6

您可以使用 postrgesql chr(int) 函数:

insert into test values (2,'|| chr(39)||'my users'||chr(39)||');
于 2017-12-29T10:00:36.453 回答
2

如果您需要在 Pg 中完成工作:

to_json(value)

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

于 2017-12-18T17:01:02.620 回答
2
于 2021-10-29T15:40:53.940 回答