SQL 查询中的正则表达式

RegEx in SQL Query

我有一个 SQL 包含

的查询
REGEXP_REPLACE(LISTAGG(foo.name, ',') WITHIN GROUP (ORDER BY foo.name), '([^,]+)(,)+', '') AS bar

在其SELECT中。 LISTAGG 用“,”作为分隔符连接 foo.name 列的值,而 REGEXP_REPLACE 替换重复值。

当我更改 LISTAGG 以便使用“,”(逗号后跟一个空白字符)作为分隔符时,我该如何调整 REGEXP_REPLACE

编辑:

REGEXP_REPLACE 更改为 '([^,]+)(, )+' 似乎有效,我得到

CITRONENSÄURE, KALIUMSORBAT, PEKTIN

但是当将 REGEXP_REPLACE 更改为 '^([^,]+)(, )+$' 时,我仍然有重复项:

CITRONENSÄURE, CITRONENSÄURE, CITRONENSÄURE, CITRONENSÄURE, CITRONENSÄURE, KALIUMSORBAT, KALIUMSORBAT, KALIUMSORBAT, KALIUMSORBAT, KALIUMSORBAT, PEKTIN, PEKTIN, PEKTIN, PEKTIN, PEKTIN

所以,'([^,]+)(, )+' 是正确的吗,不管没有 ^$

正是您在 LISTAGG 中所做的,在逗号

后添加一个 space
'([^,]+)(, )+'

虽然你应该确保它匹配整个字符串,锚定在字符串的开头 (^) 和结尾 ($).

'^([^,]+)(, )+$'


编辑:
至于正则表达式语法,要回答问题中的编辑,如果要删除同一行中的重复项,则必须确保它与整个值匹配。例如,'([^,]+)(, )+' 将匹配 'fo[o], [o]ther'。所以我们也会匹配尾随的逗号(或字符串结尾)。

([^,]+), ((, |$))+

此表达式比您尝试使用的表达式安全得多。但是,在某些情况下它可能会失败。

SQL:

select regexp_replace(
    listagg("name", ', ') within group (order by "name")
    ,'([^,]+), ((, |$))+', '')
as "bar"
from foo;

DEMO in SQLfiddle



什么时候会失败?
该表达式不是 100% 安全的,因为第一个单词没有锚定,因此它可以在值的中间匹配。例如,它将从列表中删除 WORD

'AWORD, WORD, XXX'  ==>  'AWORD, XXX'
  ====--^^^^--

我认为没有办法避免这种情况,因为 Oracle 实现了 POSIX ERE,并且不支持环视、字边界和 \G 断言。此外,这不是删除重复值的正确方法。对于非常长的表格,您最终会得到 ORA-01489: result of string concatenation is too long

对于这种情况,我建议使用 GROUP BYDISTINCT。您可以在这篇文章中阅读:SQL/mysql - Select distinct/UNIQUE but return all columns?.