使动态 INSERT inside 函数更具可读性

Make dynamic INSERT inside function more readable

提问人:Capacytron 提问时间:11/8/2023 最后编辑:Erwin BrandstetterCapacytron 更新时间:11/9/2023 访问量:53

问:

我有一个用户定义的Postgres函数,该函数执行动态。代码是不可读的,并且由于字符串转义而很难修改它。有没有办法让它看起来更好?INSERT

这是我的代码,为简洁起见省略了一些部分:

BEGIN
    -- some code

    -- escape nightmare for teammates goes here

EXECUTE 'INSERT INTO ' || _table || E'(col1, col2, col3)  VALUES (\'' || _col1 ||
                E'\', \'' || _col2 || E'\''||  E', \'' || _col3::text ||E'\') ON CONFLICT DO NOTHING RETURNING code' INTO _code;

    -- more code
END

有没有办法简化这样的事情?E'\', \''

PostgreSQL 用户定义函数 plpgsql 动态 sql

评论


答:

0赞 gbjbaanb 11/8/2023 #1

我所做的是添加注释 - 特别是生成的查询是什么样子的。你不能改变代码的工作方式,也不应该经常这样做,当有人知道最终结果时,你会更容易理解代码是如何构建它的。

评论

0赞 Capacytron 11/8/2023
感谢您的建议,它被一堆单元测试所覆盖。很清楚它的作用,但由于转义样板,很难修改它。
1赞 Richard Huxton 11/8/2023 #2

使用格式

format('INSERT INTO %I (col1,col2,col3) VALUES (%L,%L,%L)', _table, _col1, _col2, _col3);

评论

0赞 Capacytron 11/8/2023
我在使用格式和 %L 时遇到转义字符串的问题,我已经更新了问题。
2赞 Erwin Brandstetter 11/8/2023 #3

使用 format(),就像 Richard 已经指示的那样。这不仅更具可读性,而且还修复了原始版本中明显的 SQL 注入问题。

更重要的是,根本不连接。使用子句将它们作为值传递:USING

EXECUTE format(
   'INSERT INTO %I (col1,col2,col3) VALUES ($1,$2,$3)
    ON CONFLICT DO NOTHING
    RETURNING code', _table)
INTO  _code
USING _col1, _col2, _col3::text;  -- do you need to cast?

可以肯定的是,请使用架构限定的表名 - 它不能像上面的代码那样作为单个标识符传递。架构和表名必须分开引用。看:

请务必理解并使用美元报价