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

MAH*_*AHI 377 postgresql quotes insert special-characters

我有一张桌子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');
Run Code Online (Sandbox Code Playgroud)

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

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

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

Erw*_*ter 679

'通过将单引号加倍来逃避单引号- > ''是标准方式并且当然有效.

'user's log'     -- incorrect syntax (unbalanced quote)
'user''s log'
Run Code Online (Sandbox Code Playgroud)

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

E'user\'s log'
Run Code Online (Sandbox Code Playgroud)

但这通常不是优选的.
如果你必须处理许多单引号或多层转义,你可以避免使用美元引用的字符串在PostgreSQL中引用地狱:

'escape '' with '''''
$$escape ' with ''$$
Run Code Online (Sandbox Code Playgroud)

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

$token$escape ' with ''$token$
Run Code Online (Sandbox Code Playgroud)

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

$token2$Inner string: $token1$escape ' with ''$token1$ is nested$token2$
Run Code Online (Sandbox Code Playgroud)

如果$角色在客户端软件中具有特殊含义,请注意.你可能不得不逃避它.对于像psql或pgAdmin这样的标准PostgreSQL客户端,情况并非如此.

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

  • 还值得注意的是,某些 PgJDBC 版本存在美元引用问题——特别是,它可能无法忽略美元引用字符串中的语句终止符 (;)。 (2认同)

Cra*_*ger 42

这是一个很糟糕的世界,因为你的问题意味着你的应用程序中可能存在大量的SQL注入漏洞.

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

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

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

内置的报价功能quote_literalquote_identPostgreSQL中,但它们对于PL/PgSQL使用功能EXECUTE.这些日子quote_literal大多被淘汰EXECUTE ... USING,这是参数化版本,因为它更安全,更容易.您不能将它们用于此处解释的目的,因为它们是服务器端功能.


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

insert into test values (1,'');DROP SCHEMA public;--');
Run Code Online (Sandbox Code Playgroud)

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

insert into test values (1,'');
DROP SCHEMA public;
--');
Run Code Online (Sandbox Code Playgroud)

哎呀,有你的数据库.

  • 我经常使用像这样的文字插件来引导数据,以及DDL.让我们试着回答问题,而不是像"你做错了"这样的回答 (8认同)
  • @ThatDataGuy 公平评论,但在这个问题中,OP 添加了一条评论,说`数据库由 java` 访问,所以这确实直接解决了这个问题。让来到这里的人们意识到潜在的危险也非常重要,特别是考虑到 SQL 注入是软件漏洞的第一大原因。一旦意识到问题,人们就可以在什么时候无关紧要时做出明智的决定,比如你的引导用例。 (8认同)
  • 确切地。人们也经常复制和粘贴代码。当我不再每天在生产代码中看到 SQL 注入漏洞的那一天,我将停止警告人们这一点。 (5认同)
  • 这个问题和答案应该是任何即将参加的软件开发人员考试的一部分。OP 操作“可能是安全的”,但不断提醒最有经验的人注意危险确实很好。 (3认同)
  • @Davos 同意,人们应该受到警告,但我认为不应该有一个独立的警告答案。最好通过以下过程警告人们: i) 对每个答案写一条评论,要求作者在他们的答案前加上警告;ii) 如果作者在 7 天内没有更新,那么您进入那里并用序言编辑答案。 (2认同)

Cla*_*dix 19

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

 To include a single-quote character within a string constant, write two 
 adjacent single quotes, e.g. 'Dianne''s horse'.
Run Code Online (Sandbox Code Playgroud)

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

  • @MAHI如果有这样的函数,它将在PgJDBC中,而不是在PostgreSQL中,因为转义必须在客户端完成.没有这样的记录公共功能,因为它是一个*可怕的想法.您应该使用参数化语句,这样您就不需要进行任何可能不可靠的转义. (3认同)

小智 8

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

 insert into test values (1,'user''s log');
 insert into test values (2,'''my users''');
 insert into test values (3,'customer''s');
Run Code Online (Sandbox Code Playgroud)

  • 这只是重复已经提供的其他答案. (15认同)
  • 如果您有带引号的字符串,请投票显示三引号 (4认同)

小智 5

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

insert into test values (2,'|| chr(39)||'my users'||chr(39)||');
Run Code Online (Sandbox Code Playgroud)