PostgreSQL RETURNING 失败并出现 REGEXP_REPLACE

Posted

技术标签:

【中文标题】PostgreSQL RETURNING 失败并出现 REGEXP_REPLACE【英文标题】:PostgreSQL RETURNING fails with REGEXP_REPLACE 【发布时间】:2017-11-07 09:57:09 【问题描述】:

我正在运行 PostgreSQL 9.4,并且正在向我的数据库中插入大量记录。我在插入后使用 RETURNING 子句以供进一步使用。

当我简单地运行时:

... RETURNING my_car, brand, color, contact

一切正常,但如果我尝试使用 REGEXP_REPLACE 它会失败:

... RETURNing my_car, brand, color, REGEXP_REPLACE(contact, '^(\+?|00)', '') AS contact

它失败了:

ERROR: invalid regular expression: quantifier operand invalid

如果我只是直接在 PostgreSQL 中运行查询,它确实可以工作并返回一个不错的输出。

【问题讨论】:

请确保您不会意外关闭standard_conforming_strings(即select current_setting('standard_conforming_strings'))。 -- 9.1 及以后默认启用。 如果off,那么语法就是'^(\\+?|00)'。此外,还有一种特殊的语法,无论此选项如何都有效:E'^(\\+?|00)'。但留下它on 通常不那么令人惊讶。 已开启。手动运行 regexp_replace 查询也可以,但是将其添加到 RETURNING 会导致插入失败。 您能否填写失败的contact 的值?... @VaoTsun 可以在每个会话中设置 @VaoTsun 它在所有情况下都失败,例如。 '+4422848566'。但是手动运行查询是可行的。同样,只有在 RETURNING 子句中才会失败。 【参考方案1】:

尝试复现失败:

t=# create table s1(t text);
CREATE TABLE
t=# insert into s1 values ('+4422848566') returning REGEXP_REPLACE(t, '^(\+?|00)', '');
 regexp_replace
----------------
 4422848566
(1 row)

INSERT 0 1

如此阐述@pozs 建议的原因:

set standard_conforming_strings to off;

导致

WARNING:  nonstandard use of escape in a string literal
LINE 1: ...alues ('+4422848566') returning REGEXP_REPLACE(t, '^(\+?|00)...
                                                             ^
HINT:  Use the escape string syntax for escapes, e.g., E'\r\n'.
ERROR:  invalid regular expression: quantifier operand invalid

更新 正如 OP 作者所说,standard_conforming_stringson,默认情况下从 9.1 开始使用 psql 并且是 off 使用 pg-prommise

从vitally-t更新

问题只是 javascript 文字转义,而不是 标志。

他在回答中进一步阐述

【讨论】:

我正在使用 nodejs 的 pg-promise 来启动会话并使用数据库。 是的...似乎这是一个standard_conforming_strings问题,正如您所描述的那样。只是不知道如何告诉 nodejs 开启它,因为它通常在使用 psql 时开启。 联系pg-promise的作者或将标题改为Confusion with default value of standard_conforming_strings in pg-promise,并在问题中添加标签pg-promise(他时不时看这里)。 如果我没记错的话 - pg-promise 只是使用 briancs pg,顺便说一句不会改变 standard_conforming_strings 的默认值 好的,我明白了。当我通过 pgsql 登录时,“standard_conforming_strings”处于打开状态。但是通过 pg-promise 运行查询需要对字符串进行 \\ 转义。【参考方案2】:

环境变量standard_conforming_strings的当前值在这里无关紧要。如果您在查询前加上SET standard_conforming_strings = true;,您可以看到它,这不会改变任何内容。

从客户端传入未转义的正则表达式字符串与在命令行中使用 E 前缀相同:E'^(\+?|00)'

在 JavaScript 中,\ 被视为特殊符号,您只需始终提供 \\ 来指示符号,这正是您的正则表达式所需要的。

除此之外,pg-promise 将正确转义所有内容,这是一个示例:

db.any("INSERT INTO users(name) VALUES('hello') RETURNING REGEXP_REPLACE(name, $1, $2)", ['^(\\+?|00)', 'replaced'])

要了解命令行的工作原理,请在正则表达式字符串前面加上 E:

db.any("INSERT INTO users(name) VALUES('hello') RETURNING REGEXP_REPLACE(name, E$1, $2)", ['^(\\+?|00)', 'replaced'])

你会得到同样的错误:invalid regular expression: quantifier operand invalid

【讨论】:

以上是关于PostgreSQL RETURNING 失败并出现 REGEXP_REPLACE的主要内容,如果未能解决你的问题,请参考以下文章

如何在 PostgreSQL 中使用 RETURNING 和 ON CONFLICT?

postgresql update returning

Postgresql INSERT RETURNING 复杂类型

如何从另一个 php 文件中使用 PostgreSql 的 CURRVAL / RETURNING?

PostgreSql INSERT FROM SELECT RETURNING ID

PostgreSQL v12.6 中的 PLpgSQL INSERT-RETURNING-INTO 错误?