【问题标题】:Convert "regexp_substr" (Oracle ) to PostgreSQL将“regexp_substr”(Oracle)转换为 PostgreSQL
【发布时间】:2015-11-11 02:58:48
【问题描述】:

我在 Oracle SQL 中有查询:

       select town_name, 
              regexp_substr(town_name, '[^A,]+', 1, 1) as c1,
              regexp_substr(town_name, '[^A,]+', 1, 2) as c2, 
              regexp_substr(town_name, '[^A,]+', 1, rownum) as c_rownum,
              rownum
          from epr_towns

结果的前 2 行是:

VALGANNA        V   LG  V   1
VARANO BORGHI   V   R   R   2

我需要在 PostgreSQL 上获得相同的结果(对于带有regexp_substr(town_name, '[^A,]+', 1, rownum) as c_rownum 的行),我不知道如何。 你可以帮帮我吗? 谢谢。

【问题讨论】:

  • 输入是“town_name”(第一行是“VALGANNA”)。
  • 实际值为 VALGANNA 和 VARANO BORGHI(第 1 列)。第 2..4 列是在 Oracle 中使用“regexp_substr”获得的结果。
  • 警告!当列表中有 NULL 元素时,通常用于解析分隔字符串的格式 '[^A,]+' 的正则表达式会失败。确保彻底测试。总是期待意外!有关更多详细信息和改进的正则表达式,请参见此处。我不知道它会如何转化为 Postgres:stackoverflow.com/questions/31464275/…

标签: oracle postgresql rownum regexp-substr


【解决方案1】:

我没有表格,所以我使用 generate 例如:

   select town_name, 
          regexp_substr(town_name, '[^A,]+', 1, 1) as c1,
          regexp_substr(town_name, '[^A,]+', 1, 2) as c2, 
          regexp_substr(town_name, '[^A,]+', 1, dense_rank() over (order by town_name)) as c_rownum,
          dense_rank() over (order by c)
      from epr_towns

我相信你在寻找dense_rank窗口函数?..

注意。拥有 SQL 小提琴或初始代码总是更容易

【讨论】:

  • 我一直在寻找dense_rank() 和regexp_substr() 的4 个参数的转换(对于2 个参数,它的工作原理是“substring(town_name, '[^A,]+')”)
【解决方案2】:

这里确实有两个不同的问题

  • 替换行号
  • 将 regexp_substr 替换为 regexp_matches

要求解 rownum,请使用 CTE(WITH 子句)将类似于 rownum 的列添加到基础表中。

regexp_matches 与 Oracle regexp_substr 的工作方式略有不同。 Oracle regexp_substr 将第 n 个匹配项作为参数,而 PostgreSQL regexp_matches所有 个匹配项作为表值函数返回。因此,您必须将调用包装在具有限制/偏移的子查询中以提取第 n 个匹配项。此外,regexp_substr 返回的行是数组,因此假设您的正则表达式中没有带括号的表达式,您需要索引/取消引用数组中的第一项。

最终结果如下所示:

http://sqlfiddle.com/#!17/865ee/7

 with epr_towns_rn as (
    select town_name,
      row_number() over(order by town_name) as rn
  from epr_towns
)
select town_name,
   (select (regexp_matches(town_name, '[^A,]+', 'g'))[1] offset 0 limit 1) as c1,
   (select (regexp_matches(town_name, '[^A,]+', 'g'))[1] offset 1 limit 1) as c2,
   (select (regexp_matches(town_name, '[^A,]+', 'g'))[1] offset rn-1 limit 1)
     as c_rownum,
   rn
   from epr_towns_rn;

如果您只想要第一个匹配项,您可以省略 'g' 参数并省略子查询的限制/偏移量,但如果没有匹配项,您仍然需要子查询包装器,以模拟 regexp_substr 在没有匹配项时返回 null匹配。

【讨论】:

    【解决方案3】:

    您可以在此页面上找到您的案例和其他场景: https://pgxn.org/dist/orafce/doc/sql_migration/sql_migration03.html

    --

    简而言之,您可以执行以下操作: 来自 OracleDB:

    SELECT
        REGEXP_SUBSTR('one two three four five ',
        '(\S*)\s') AS "REGEXP"
    FROM DUAL;
    

    结果:一个

    到 PostgreSQL:

    SELECT (
        SELECT array_to_string(a, '') AS "REGEXP"
        FROM regexp_matches('one two three four five ',
        '(\S*)\s',
        'g') AS f(a)
        LIMIT 1
    );
    

    结果:一个

    【讨论】:

      猜你喜欢
      • 2021-10-15
      • 2023-01-17
      • 2021-01-10
      • 2018-09-26
      • 2023-02-01
      • 2015-09-12
      • 2011-01-17
      • 2019-03-04
      相关资源
      最近更新 更多