编写/调试复杂PL/pgSQL查询的最佳实践
简而言之:编写和调试PostgreSQL查询的最佳方法是什么?这些查询使用过程编程技术,例如使用pl/pgsql?我对编写这些类型的过程性查询非常陌生,因此如果我没有找到一个真正简单的解决方案,请提前道歉 具体说明:我正在编写一些相对复杂的SQL查询,它们利用现有的pl/pgsql函数,理想情况下会使用大量变量,使查询易于调试和修改。下面的示例代码非常简单;我的实际用例要复杂得多 我的第一个解决方案是将所有东西都嵌入到函数中,但这太笨重了。由于我必须显式声明返回类型,因此修改代码非常困难:编写/调试复杂PL/pgSQL查询的最佳实践,sql,postgresql,plpgsql,procedural-programming,Sql,Postgresql,Plpgsql,Procedural Programming,简而言之:编写和调试PostgreSQL查询的最佳方法是什么?这些查询使用过程编程技术,例如使用pl/pgsql?我对编写这些类型的过程性查询非常陌生,因此如果我没有找到一个真正简单的解决方案,请提前道歉 具体说明:我正在编写一些相对复杂的SQL查询,它们利用现有的pl/pgsql函数,理想情况下会使用大量变量,使查询易于调试和修改。下面的示例代码非常简单;我的实际用例要复杂得多 我的第一个解决方案是将所有东西都嵌入到函数中,但这太笨重了。由于我必须显式声明返回类型,因此修改代码非常困难: CR
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:那么我必须修改退货类型。这种情况会经常发生,而且必须一次又一次地更改返回类型是很烦人的
我尝试的下一个解决方案是不使用函数,并尝试以下方法:
这也不起作用:
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编程,有一种优雅和/或标准的解决方案吗?为什么不直接调用plpgsql函数 只做: SELECT user_id, id, created_at -- possibly a ton of other complicated stuff involving other functions and variables FROM my_schema.my_other_fcn() 我不喜欢这种类型的plpgsql编程包装查询。您可以阻止非常有效的planner—因为plpgsql函数是优化器的黑盒—所以您可能会在大数据上遇到可怕的性能问题。PLpgSQL函数不应替代视图
语句不应返回任何结果。简单-PostgreSQL函数不应替代PostgreSQL视图。像这样直接调用嵌入函数作为查询,据我所知,不允许在查询中使用变量、循环等。这就是作者的意图——可能是一大堆涉及其他函数和变量的复杂东西。关于性能,在本文中我并不关心这一点。如果您需要变量、循环和可能的返回,那么您需要使用函数—DO语句太有限—并且没有任何其他可能性。