【问题标题】:Escaping a LIKE pattern or regexp string in Postgres 8.4 inside a stored procedure在存储过程中转义 Postgres 8.4 中的 LIKE 模式或正则表达式字符串
【发布时间】:2015-06-07 08:15:40
【问题描述】:

我正在编写一个存储过程来查找主项的子项并对其进行更新。剧情是这样的

Id  Item Name               Parent Id  
1   Item A 14.1             NULL  
2   Item B 14.1.1           1      
3   Item C 14.1.2           1       
4   Item B 14.1.3           1       
5   Item A 14.1.1.1         2 

我在 SO String matching in PostgreSQL 8.4 上发布了另一个问题,以获取项目的子项。根据该答案,我必须转义项目代码并必须在查询中使用它。但是我没有任何方法可以逃脱。 SP如下:

CREATE OR REPLACE FUNCTION updateitemparentnew(bigint, int) RETURNS text
    LANGUAGE plpgsql STRICT
    AS $$
DECLARE
    itemdetail RECORD;    
    codeSearch text;
    codeEscapedSearch text;
    result text;
BEGIN   

--Get th details of the current item
SELECT INTO itemdetail * FROM om_item WHERE item_id = $1;

codeSearch = itemdetail.item_code||'.';
codeEscapedSearch = codeSearch;  --Need to be corrected. It should escape the item code

-- Event 1=> add 2 => edit 3 => delete
IF $2 = 1 THEN
    --Find new children and update then
    result =  'UPDATE om_item SET item_parentid = '||itemdetail.item_id
           ||' WHERE item_id IN (
                 SELECT item_id FROM om_item
                 WHERE  item_code LIKE \''||codesearch||'%\'
                 AND item_code ~ \''||codeEscapedsearch||'[^.]+$\');';

END IF;

return result;
END;
$$;

在查询中codeEscapedSearch 应该被转义以处理代码本身中的. 和正则表达式中的.

【问题讨论】:

    标签: regex postgresql stored-procedures plpgsql


    【解决方案1】:

    考虑这种直接的方法:

    CREATE OR REPLACE FUNCTION updateitemparentnew(_id bigint, _operation text)
      RETURNS void LANGUAGE plpgsql STRICT AS
    $func$
    DECLARE
       code_like text;
       code_regex text;
    BEGIN
    
    SELECT INTO code_like, code_regex
           p.item_code || '.%'
         , '^' || replace(p.item_code, '.', '\.') || '\.[^.]+$'
    FROM   om_item p
    WHERE  p.item_id = _id;
    
    CASE _operation  -- ins / upd / del
    WHEN 'upd' THEN  -- Find new children and update then
       UPDATE om_item c
       SET    item_parentid = _id
       WHERE  c.item_code LIKE code_like
       AND    c.item_code ~ code_regex;
    
    -- WHEN 'ins' THEN ...
    -- WHEN 'del' THEN ...
    END CASE;
    
    END
    $func$;
    

    这不会返回查询字符串,而是直接执行UPDATE。更短更快。

    也使用replace(),顺便说一句。

    彻底解决所有LIKE 和正则表达式模式:

    【讨论】:

    • 感谢您的回答。我决定分配一个新变量,因为我也需要在接下来的两个操作中重复它(编辑/删除)。
    • 另外我把 `\` 认为需要转义斜线。无论如何感谢您的意见。
    • @NandakumarV:您需要注意 plpgsql 与其他编程语言不同。任务相对昂贵。尽量在 SQL 语句中做。
    • @NandakumarV:我用变量调整了函数以允许重用模式。
    • 因此将数据保存到 sql 查询中比将其分配给变量要快。感谢您提供的信息。
    【解决方案2】:

    由于没有找到合适的解决方案,我决定使用简单的replace
    codeEscapedSearch = replace(codeSearch,'.','\\.');

    【讨论】:

    • replace() 可以,但不需要 \\,只需 \。我将提出一个完全不同的功能。
    猜你喜欢
    • 2011-07-05
    • 2021-12-22
    • 1970-01-01
    • 2010-09-21
    相关资源
    最近更新 更多