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_strings
是 on
,默认情况下从 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 INSERT RETURNING 复杂类型
如何从另一个 php 文件中使用 PostgreSql 的 CURRVAL / RETURNING?