【问题标题】:Postgresql - Chain multiple regex_replace functions in single query?Postgresql - 在单个查询中链接多个 regex_replace 函数?
【发布时间】:2019-11-29 06:18:11
【问题描述】:

使用Postgresql 11.6。我在 tab_a.sysdescr 中有值,我想使用 regex_replace 进行转换,并将这些转换后的值更新为 tab_b.os_type。

这是表 tab_a,其中包含 sysdescr 中的源字符串:

   hostname  |   sysdescr      |
-------------+-----------------+
   wifiap01  | foo HiveOS bar  | 
   switch01  | foo JUNOS bar   | 
   router01  | foo IOS XR bar  |

这是我更新的目标表 tab_b,在列 os_type 中:

   hostname  |   mgmt_ip    | os_type
-------------+--------------+---------
   wifiap01  | 10.20.30.40  | 
   switch01  | 20.30.40.50  | 
   router01  | 30.40.50.60  |

这是示例tab_b 的期望状态

   hostname  |   mgmt_ip    | os_type
-------------+--------------+---------
   wifiap01  | 10.20.30.40  | hiveos
   switch01  | 20.30.40.50  | junos
   router01  | 30.40.50.60  | iosxr

我有一个可以针对单个 os_type 工作的有效查询。在此示例中,HiveOS

UPDATE tab_b
SET os_type = (
    SELECT REGEXP_REPLACE(sysdescr, '.*HiveOS.*', 'hiveos')
    FROM tab_a
    WHERE tab_a.hostname = tab_b.hostname
)
WHERE EXISTS (
    SELECT sysdescr
    FROM tab_a
    WHERE tab_a.hostname = tab_b.hostname
);

我不知道如何将多个regex_replace 函数“链接”到一个查询中,或者通过嵌套的子查询。在 SELECT REGEX_REPLACE 之后添加 'OR' 行不起作用,并且无法在网上找到类似的示例。

End-goal 是一个查询函数,它将按照指定替换字符串,更新 tab_b 中所有行上的替换字符串。我希望避免深入研究PL/Python,但如果这是解决这个问题的最佳方法,那没关系。理想情况下,我可以定义第三个表,其中包含模式和replacement_string arguments - 并且可以以某种方式对其进行迭代。

编辑:我想要完成的示例

这不是有效的代码,但希望能证明我想要完成的工作。可以执行一次的单个查询,并将表中的每个sysdescr 转换/转换为新表中os_type 的正确值。

UPDATE tab_b
SET os_type = (
    SELECT REGEXP_REPLACE(sysdescr, '.*HiveOS.*', 'hiveos') OR
    SELECT REGEXP_REPLACE(sysdescr, '.*JUNOS.*', 'junos') OR
    SELECT REGEXP_REPLACE(sysdescr, '.*IOS XR.*', 'iosxr')
    FROM tab_a
    WHERE tab_a.hostname = tab_b.hostname
)
WHERE EXISTS (
    SELECT sysdescr
    FROM tab_a
    WHERE tab_a.hostname = tab_b.hostname
);

【问题讨论】:

    标签: postgresql subquery


    【解决方案1】:

    如果 foobar 在所有行中都是一致的(如您的示例中所示),那么这应该有效:

    postgres=# SELECT lower(replace(regexp_replace('foo IOS XR bar','foo (.*) bar','\1'),' ',''));
     lower 
    -------
     iosxr
    (1 row)
    

    简而言之,它执行以下操作:

    1. regexp_replace() 从正面和背面剪掉foobar
    2. 删除带有replace() 的空格
    3. 带有lower()的文本小写

    如果您需要进一步删除foobar,您可以嵌套字符串函数,如上所示。

    【讨论】:

    • foo 和 bar 只是示例文本,它们将围绕我正在寻找的匹配字符串。提取/翻译我需要的值是我正在做的事情(见问题)。但它仅适用于单个源/模式集。我正在寻找一种方法来定义将与多个字符串模式匹配的单个查询。我编辑了我的问题,试图更好地解释它。谢谢,
    • 你看过这个帖子吗:stackoverflow.com/questions/28938905/…
    • 我刚刚发布了答案。能够使用第三个(查找)表来解决。谢谢!
    【解决方案2】:

    我能够使用第三个表(查找表)来解决这个问题。它包含两列,一列保存匹配字符串,一列保存返回字符串。

    新表tab_lookup

     id |                   match_str                   | return_str
    ----+-----------------------------------------------+------------
      1 | HiveOS                                        | hiveos
      2 | IOS XR                                        | iosxr
      3 | JUNOS                                         | junos
      5 | armv                                          | opengear
      6 | NX-OS                                         | nxos
      7 | Adaptive Security Appliance                   | asa
     17 | NetScreen                                     | netscreen
     19 | Cisco Internetwork Operating System Software  | ios
     18 | Cisco IOS Software                            | ios
     20 | ProCurve                                      | hp
     21 | AX Series Advanced Traffic Manager            | a10
     22 | SSG                                           | netscreen
     23 | M13, Software Version                         | m13
     24 | WS-C2948                                      | catos
     25 | Application Control Engine Appliance          | ace
    

    使用此查询,我可以使用来自tab_lookup.return_str 的适当值更新tab_b.os_type

    UPDATE tab_b
    SET os_type = (
        SELECT return_str
        FROM tab_lookup
        WHERE EXISTS (
            SELECT regexp_matches(sysdescr, match_str)
            FROM tab_a
            WHERE tab_a.hostname = tab_b.hostname
        )
    );
    

    我遇到的唯一问题是给定行必须只有一个匹配项。但这很容易通过详细的 match_str 值来实现。例如,不要使用“IOS”,而是使用“Cisco IOS 软件”。

    总而言之,对这个解决方案非常满意,因为随着更多设备类型被添加到网络中,它提供了一种更新查找值的简单方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-23
      • 2018-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多