编写/调试复杂 PL/pgSQL 查询的最佳实践
Posted
技术标签:
【中文标题】编写/调试复杂 PL/pgSQL 查询的最佳实践【英文标题】:Best practices for writing / debugging complex PL/pgSQL queries 【发布时间】:2014-11-23 23:37:19 【问题描述】:简而言之:使用过程编程技术(例如使用 pl/pgsql)编写和调试 PostgreSQL 查询的最佳方法是什么?我对编写这些类型的程序查询很陌生,所以如果我还没有找到一个非常简单的解决方案,请提前道歉。
细节:我正在编写一些(相对)复杂的 SQL 查询,它们利用现有的 pl/pgsql 函数,理想情况下会利用大量变量来使查询易于调试和修改。 (下面的示例代码故意简单;我的实际用例要复杂得多。)
我的第一个解决方案是将所有内容嵌入到函数中,但这很笨重。由于我必须显式声明返回类型,因此修改代码很痛苦:
CREATE OR REPLACE FUNCTION
my_schema.my_fcn()
RETURNS TABLE(user_id integer,
id integer,
created_at timestamp) AS
$BODY$
DECLARE
_id_select integer = 10;
BEGIN
RETURN QUERY
SELECT
user_id,
id,
created_at
WHERE id = _id_selector
-- possibly a ton of other complicated stuff involving other functions and variables
FROM my_schema.my_other_fcn()
END;
$BODY$
LANGUAGE plpgsql;
(编辑:使查询更加不平凡。)
现在假设我想在查询中添加order_total
并去掉id
:那么我必须修改返回类型。这会经常发生,而且必须一遍又一遍地更改返回类型,这很烦人。
我尝试的下一个解决方案是不使用函数,并尝试以下方式:How can I execute pl/pgsql code without creating a function? 这也不起作用:
DO $$
DECLARE
_id_select integer = 10;
BEGIN
SELECT
user_id,
id,
created_at
WHERE id = _id_selector
-- possibly a ton of other complicated stuff involving other functions and variables
FROM my_schema.my_other_fcn()
END $$;
产生的错误:
ERROR: query has no destination for result data
HINT: If you want to discard the results of a SELECT, use PERFORM instead.
CONTEXT: PL/pgSQL function inline_code_block line 4 at SQL statement
********** Error **********
ERROR: query has no destination for result data
我不想使用PERFORM
,因为实际上我确实想查看查询结果。
这种类型的 SQL 编程是否有优雅和/或标准的解决方案?
【问题讨论】:
【参考方案1】:为什么不直接调用plpgsql函数?
只做:
选择 用户身份, ID, created_at -- 可能还有很多涉及其他函数和变量的复杂内容 FROM my_schema.my_other_fcn()我不喜欢这种风格的 plpgsql 编程——包装查询。您可以阻止非常有效的规划器 - 因为 plpgsql 函数是优化器的黑匣子 - 所以您可以预料到大数据上会出现可怕的性能问题。 PLpgSQL 函数不应替代视图。
语句 DO 不应返回任何结果。简单地说——PostgreSQL 函数不应该替代 PostgreSQL 视图。
【讨论】:
像这样直接调用嵌入式函数作为查询(据我所知)不允许您在查询中使用变量、循环等。这就是-- possibly a ton of other complicated stuff involving other functions and variables
的意图。关于性能,在这种情况下,这不是我关心的问题。
如果你需要一个变量、循环和可能的返回值,那么你需要使用函数——DO语句太有限了——没有任何其他可能。以上是关于编写/调试复杂 PL/pgSQL 查询的最佳实践的主要内容,如果未能解决你的问题,请参考以下文章