postgresQL 更新列,其值来自正则表达式 + 更多

Posted

技术标签:

【中文标题】postgresQL 更新列,其值来自正则表达式 + 更多【英文标题】:postgres SQL update column with value from regex + more 【发布时间】:2018-11-22 17:52:43 【问题描述】:

我想更新 db.table.column 中所有匹配的 url。我想在 url 的末尾添加一个参数,并将其他所有内容保持原样。

我试过这个:

UPDATE table SET column = regexp_replace(column, 'url_matcher', (substring(column, 'url_matcher') || 'end_param');

UPDATE
    "db"."emailTemplate"
set 
    "bodyText" = regexp_replace(
        "bodyText",
        '((@root\.)?app\.url)[a-zA-Z0-9@:%._\+~#\-&=\/?]2,255',
        (substring("bodyText" from '((@root\.)?app\.url)[a-zA-Z0-9@:%._\+~#\-&=\/?]2,255') || '&param=param')
    ),
    "bodyhtml" = regexp_replace(
        "bodyHtml",
        '((@root\.)?app\.url)[a-zA-Z0-9@:%._\+~#\-&=\/?]2,255',
        (substring("bodyHtml" from '((@root\.)?app\.url)[a-zA-Z0-9@:%._\+~#\-&=\/?]2,255') || '&param=param')
    );

但子字符串不匹配整个 url 它只匹配 app.url 或 @root.app.url url 的其他所有内容都不匹配。

当我单独运行 regexp_replace("bodyHtml", [same pattern], 'replace_thing') 时,它会匹配整个 url 并将其替换为 "replace_thing"。因此,在一种情况下,正则表达式模式有效,而在另一种情况下则无效。所有与 url 不匹配的字段都不会更新,但在使用 substring 函数时也会更新,如我的示例所示。所有与 url 不匹配的字段都更新为 null。

    我不能像这样使用嵌套函数吗?如果不是 - 我怎样才能实现我想要的?

    除了 regexp_replace 之外,其他正则表达式模式规则是否适用于子字符串函数?

列值的最大值:Hello user, click here app.url/home:search=true&item=33 to visit your page regexp_replace 将匹配:app.url/home:search=true&item=33,子字符串将仅匹配 app.url

更新后的列值应如下所示:

Hello user, click here app.url/home:search=true&item=33&param=param to visit your page

但它最终看起来像这样:

Hello user, click here app.url&param=param to visit your page

这样的字段:Hello you have been registered! 看起来像这样:null,但应该保持不变。

【问题讨论】:

看起来你只需要一个 '((@root\.)?app\.url[a-zA-Z0-9@:%._+~#&=/?-]2,255)' 正则表达式和 '\1&param=param' 替换。见rextester.com/MHVIX41178。 谢谢,这对我帮助很大!我不知道 \1 作为参考。 【参考方案1】:

正则表达式模式用于搜索匹配的文本。在替换模式中,您不能使用正则表达式,只能使用特定的构造,例如替换反向引用如 \1 来引用捕获组 1 值。另外,替换时需要特殊的回调来修改匹配值,这里不支持。

您可以使用 () 包装整个模式(以创建捕获组)并使用如下正则表达式:

'((@root\.)?app\.url[a-zA-Z0-9@:%._+~#&=/?-]2,255)'

替换后的样子

'\1&param=param'

其中\1 是对第 1 组值的替换反向引用。见online demo

select regexp_replace('Hello user, click here app.url/home:search=true&item=33 to visit your page',
                      '((@root\.)?app\.url[a-zA-Z0-9@:%._+~#&=/?-]2,255)',
                      '\1&param=param');

【讨论】:

在我看来 \1 (group 1) 只匹配 app.url \2 (group 2) 只匹配 @root。 - 在追逐我提出的地方。完整匹配的反向引用是什么? @RasmusPuls () 包裹整个模式(以创建捕获组)。 PostgreSQL regexp_replace 不支持对整个匹配值的替换反向引用。此外,确保-+ 没有被转义,并将- 移动到括号表达式的末尾。只需使用我在答案中的表达即可。您的模式中的 \/ 实际上是两个字符,\/,它不是转义的 /,它只会在某些(例如 JS 正则表达式)中匹配 /

以上是关于postgresQL 更新列,其值来自正则表达式 + 更多的主要内容,如果未能解决你的问题,请参考以下文章

在 PostgreSQL 列中搜索子字符串

如何创建一列数组,其值来自一列并且它们的长度来自pyspark数据帧中的另一列?

正则表达式或 LIKE 模式的转义函数

Postgresql 正则表达式转

sql 通过将其值减1来更新列

如何使用 laravel 更新 postgresql 数据库中的 json 数据?