在 PostgreSQL 中插入带单引号的文本

Insert text with single quotes in PostgreSQL

提问人:MAHI 提问时间:9/7/2012 最后编辑:Erwin BrandstetterMAHI 更新时间:3/15/2023 访问量:689125

问:

我有一张桌子。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转义机制?

SQL PostgreSQL 引用字符串 文本

评论

1赞 Richard Huxton 9/7/2012
使用客户端库提供的任何转义值。有关更多信息,您必须说明您如何访问数据库。
0赞 MAHI 9/7/2012
@Richard Huxton 数据库是通过 java 访问的。
2赞 Richard Huxton 9/7/2012
因此,请使用标准的 jdbc 占位符。或者解释为什么这不是最好的选择。
1赞 MAHI 9/7/2012
@Richard Huxton,我并不是说这不是最好的选择,我正在搜索他们是否在SQL中存在任何转义方法来做到这一点。
0赞 Richard Huxton 9/7/2012
好吧,请参阅下面的 @Claudix 的回复,但显然值文本需要根据其类型进行不同的转义 postgresql.org/docs/current/static/datatype.html

答:

65赞 Claudi 9/7/2012 #1

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

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

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

评论

0赞 MAHI 9/7/2012
感谢您的回复,但是我必须使用它手动转义每个字符,如果它们存在任何内置函数来执行此操作?
3赞 Craig Ringer 9/7/2012
@MAHI 如果有这样的函数,它将在 PgJDBC 中,而不是在 PostgreSQL 中,因为转义必须在客户端完成。没有这种记录在案的公共功能,因为这是一个糟糕的想法。您应该使用参数化语句,这样您就不需要执行任何可能不可靠的转义操作。
55赞 Craig Ringer 9/7/2012 #2

这真是太糟糕了,因为你的问题意味着你的应用程序中可能存在巨大的 SQL 注入漏洞。

应使用参数化语句。对于 Java,请使用带有占位符的 PreparedStatement。你说你不想使用参数化语句,但你没有解释为什么,坦率地说,这必须是一个很好的理由不使用它们,因为它们是解决你试图解决的问题的最简单、最安全的方法。

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

PgJDBC 中没有用于字符串引用和转义的公共函数。这在一定程度上是因为它可能让它看起来是个好主意。

PostgreSQL 中有内置的引用函数,但它们适用于使用 .这些天大多被 淘汰了,这是参数化版本,因为它更安全更容易。您不能将它们用于您在此处解释的目的,因为它们是服务器端函数。quote_literalquote_identPL/PgSQLEXECUTEquote_literalEXECUTE ... USING


想象一下,如果您从恶意用户那里获得价值会发生什么。您将生产:');DROP SCHEMA public;--

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

它分解为两个语句和一个被忽略的注释:

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

哎呀,你的数据库在那里。

评论

31赞 ThatDataGuy 11/29/2018
我经常使用这样的文字插入来引导数据,以及 DDL。让我们试着回答问题,而不是像“你做错了”这样的回答
10赞 Davos 5/3/2019
@ThatDataGuy公平的评论,但在这个问题中,OP添加了一条评论,说这确实直接解决了这个问题。对于来到这里的人来说,意识到潜在的危险也非常重要,特别是考虑到SQL注入是软件漏洞的#1原因。一旦意识到问题,人们就可以做出明智的决定,什么时候它无关紧要,比如你的引导用例。database is accessed by java
7赞 Craig Ringer 5/6/2019
完全。人们也经常复制和粘贴代码。当我不再每天在生产代码中看到 SQL 注入漏洞的那一天,我将停止警告人们。
3赞 Raymond Naseef 2/8/2020
这个问题和答案应该是任何即将到来的软件开发人员考试的一部分。OP 操作“可能是安全的”,但即使是最有经验的人也要不断提醒危险,这真的很好。
3赞 Kind Contributor 9/23/2020
@Davos 同意,人们应该被警告,但我认为不应该有一个独立的警告答案。最好通过以下过程警告人们:i) 在每个答案上写一个评论,要求作者在他们的答案前面加上警告;ii) 如果作者在 7 天内没有更新,那么你去那里编辑带有序言的答案。
1252赞 Erwin Brandstetter 9/7/2012 #3

字符串

通过加倍引号来转义单引号→是标准方法,当然也有效:'''

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

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

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

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客户端,情况并非如此。$

这对于编写 PL/pgSQL 函数或临时 SQL 命令非常有用。但是,当用户输入可能时,它无法缓解使用预准备语句或其他方法来防止应用程序中的 SQL 注入的需要。@Craig的回答还有更多。更多详情:

Postgres 中的值

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

评论

2赞 Craig Ringer 4/7/2014
还值得注意的是,某些 PgJDBC 版本存在美元引用问题 - 特别是,它可能无法忽略美元引用字符串中的语句终止符 (;)。
1赞 Erwin Brandstetter 4/7/2014
此相关答案包含有关 JDBC 问题的详细信息。
1赞 alexglue 4/9/2014
如果你想在插入时从文本列中转义,如果是过程语言等,那么你可以使用 quote_literal(column_name) 字符串函数。
0赞 filiprem 4/12/2019
@ErwinBrandstetter,re“可以嵌套任意数量的级别”:但证明二级嵌套在这里不起作用。?SELECT $outer$OUT$inner$INNER$inner$ER$outer$;
1赞 Davos 5/3/2019
我们注意到,尝试在 Redshift(实际上是旧的 Postgres 8.x)中插入字符串文字与您在这里所说的旧版本相匹配。在该平台中,如果字符串文本的反斜杠没有与以下字符的有效转义序列组合,则该反斜杠在插入时会消失,因此在这种情况下,反斜杠加倍也有效。加载 xml/html 文本值时很容易被刺痛。字面意思是(在 Redshift 中仍然如此)与转义的字面意思。很高兴您现在必须明确请求该行为。E
41赞 Hunter 9/8/2012 #4

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

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

评论

4赞 winkbrace 3/17/2020
如果您有带引号的字符串,请为显示三重引号投赞成票
0赞 ktaria 4/13/2020
up ,因为它是一个简单的解决方案
2赞 hatenine 12/19/2017 #5

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

to_json(value)

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

评论

0赞 Erwin Brandstetter 12/19/2017
这个问题与 JSON 有什么关系?
1赞 hatenine 12/19/2017
@ErwinBrandstetter,对不起,我可能要走了。但它转义了字符串中的引号
1赞 Erwin Brandstetter 12/19/2017
这完全是另一回事。您可以使用 或 来转义引号。请参见:stackoverflow.com/a/25143945/939860format()quote_literal()quote_nullable()
8赞 Slava Struminski 12/29/2017 #6

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

insert into test values (2,'|| chr(39)||'my users'||chr(39)||');
1赞 Wonz 10/29/2021 #7

当我使用 Python 将值插入到 PostgreSQL 中时,我也遇到了一个问题:“xxx”列不存在。

我在wiki.postgresql中找到了原因:

PostgreSQL对此仅使用单引号(即 )。双引号用于引用系统标识符;字段名称、表名等(即 )。
MySQL使用(重音符号或反引号)来引用系统标识符,这显然是非标准的。
WHERE name = 'John'WHERE "last name" = 'Smith'`

这意味着 PostgreSQL 只能对字段名称、表名等使用单引号。因此,您不能在值中使用单引号。

我的情况是:我想在PostgreSQL中插入值“sb的adj和sb的adj的差异”。

我如何解决这个问题:

我用 '替换 ',我用 '替换 ' 因为 PostgreSQL 值不支持双引号。

所以我认为您可以使用以下代码来插入值:

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

评论

1赞 10/29/2021
"这意味着 PostgreSQL 只能对字段名称使用单引号,表名“不,您不能对列名或表名使用单引号。无论是在 Postgres 中还是在标准 SQL 中。您可以轻松地在字符串常量中嵌入单个引号,这就是 SQL 标准中的定义方式。'user''s log'
0赞 Wonz 10/30/2021
@a_horse_with_no_name 感谢您的解决方案。测试后我发现它有效。
-1赞 MD. SHIFULLAH 12/21/2022 #8

您必须添加一个额外的单引号 -> ' 并将它们加倍引号,如下例所示 -> ' ' 是标准方法,当然有效:

错误的方式:'user's log' 正确方式: 'user's log'

问题:

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

解决 方案:

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

评论

0赞 Erwin Brandstetter 12/21/2022
这比现有的答案增加了什么?
0赞 MD. SHIFULLAH 12/21/2022
嗨,@ErwinBrandstetter,我以有条理的方式重新排列答案,以便更好地理解。我可能错了吗?还是我的这个答案错了?