【问题标题】:How do I create a nested function in PL/pgSQL?如何在 PL/pgSQL 中创建嵌套函数?
【发布时间】:2017-02-20 08:14:53
【问题描述】:

我想在 PL/pgSQL 中创建一个函数,其中包含几个嵌套(或内部)函数。这样我可以将问题分解成更小的部分,但不能在这个函数之外访问我的小部分。

在 PL/pgSQL 中可以做到这一点吗?如果有,怎么做?

【问题讨论】:

  • 你为什么要这样做?对我来说似乎不切实际。您可以将问题分解为没有很多功能的较小部分,或者如果您确实需要它 - 调整它们的权限。
  • @KamilGosciminski - 你提到你“可以将问题分解成更小的部分而没有很多功能” - 想知道你会怎么做?

标签: postgresql scope plpgsql postgresql-9.5


【解决方案1】:

试试看:

CREATE OR REPLACE FUNCTION outer() RETURNS void AS $outer$
DECLARE s text;
BEGIN
  CREATE OR REPLACE FUNCTION inner() RETURNS text AS $inner$
  BEGIN
    RETURN 'inner';
  END;
  $inner$ language plpgsql;

  SELECT inner() INTO s;
  RAISE NOTICE '%', s;

  DROP FUNCTION inner();
END;
$outer$ language plpgsql;

在 postgres 9.5 SELECT outer(); 输出中

 psql:/vagrant/f.sql:14: NOTICE:  inner

编辑:如果你不放弃内部 函数在外部函数的末尾,它将对数据库的其余部分保持可见。

【讨论】:

  • 有几件事要向其他尝试此操作的人指出:您不能只将AS $$ 用于内部和外部功能。此外,如果您的函数有参数,则必须在删除该函数时传递类型。而且你不能在外部函数的DECLARE 部分调用你的函数,因为它们还没有被创建。只需在创建嵌套函数后创建变量并为其赋值即可。
  • @Gregory:更重要的一点:如果两个并发事务尝试调用此函数,则第二个事务将阻塞内部CREATE,直到第一个事务提交,因为数据库的唯一性约束函数名称。您可以通过将内部函数放入会话的临时模式来解决此问题,即使用CREATE FUNCTION pg_temp.inner()。额外的好处是内部函数永远不会在外部可见,并且会在您的会话结束后自动清理。
  • @Gregory:顺便说一句,DECLARE ... BEGIN ... END 块可以嵌套,所以你可以在创建内部函数后进行声明
  • 在每个(外部)函数调用上创建一个新的(内部)函数似乎很浪费。
【解决方案2】:

PLpgSQL 不支持嵌套函数。仿真没有任何意义,而且是非生产性的。

【讨论】:

  • 乍一看,kiwi 描述的仿真是有效的。我在较小的数据集上对其进行了测试,它看起来不错。然而,当使用较大的日期集时,它总是会因非常奇怪的锁定错误而失败。我认为阅读这篇文章的人最好不要试图强制嵌套函数在 PL/pgSQL 中工作。
  • @GregoryArenius:我对那个例子做了一些尝试,每次调用函数“outer”时,它都会创建/替换函数“inner”(与“outer”函数在同一范围内),因此很奇怪错误。它根本不是一个“内部函数”,它也无法访问“外部”的内部范围。
猜你喜欢
  • 2012-08-10
  • 1970-01-01
  • 1970-01-01
  • 2012-08-12
  • 1970-01-01
  • 2018-12-16
  • 2011-02-03
  • 2016-07-07
  • 2017-12-10
相关资源
最近更新 更多