PostgreSQL plpgsql 获取当前程序 oid
Posted
技术标签:
【中文标题】PostgreSQL plpgsql 获取当前程序 oid【英文标题】:PostgreSQL plpgsql get current procedures oid 【发布时间】:2015-08-14 09:01:32 【问题描述】:是否可以在函数中获取当前 OID?喜欢:
CREATE FUNCTION foo()
RETURNS numeric
LANGUAGE plpgsql
AS '
BEGIN
return THIS_FUNCTIONS_OID;
END
';
我需要这个,因为我在不同的模式中创建了函数 foo
,所以函数名称在这里没有帮助。
【问题讨论】:
我不确定,但是……为什么?你想用这个解决什么问题? 最后,我想获取创建函数的模式的名称。我需要这个来在运行时操作search_path
。
我认为这不可能。请参阅来自 Postgres 主要贡献者之一的this answer。此后,他添加了support for callstack dumps,它将为您提供函数名称,但不幸的是,它似乎没有任何模式限定。
感谢您提供此信息!
【参考方案1】:
我猜你看起来很像
return select oid from pg_proc where proname='$0';
我怀疑你能不能把它当作变量。您可以从current_query()
获取名称,但它非常不可靠...除非您每次调用时都将函数名称定义为第一个参数:),否则您可以使用 $1,但它也不太可靠。 ..
【讨论】:
这对我没有帮助。函数foo
是在不同的模式中创建的(都在search_path
中)。所以我们的选择会返回不止一个 oid。
哦,那么只返回硬编码的模式名称?.. 不同模式中的每个 foo 都不同
这里没有选项。【参考方案2】:
我不知道你在做什么,但我敢肯定你做得不好:)。通常,这些奇怪的要求与奇怪的设计相关,导致代码难以维护。
但是您可以使用 PostgreSQL 9.4 及更高版本轻松获取当前函数的oid
。 (此信息在 C PL 函数中很容易访问,但在 PLpgSQL 中隐藏。)如果您的函数来自 public
以外的其他模式,则容易得多:
CREATE OR REPLACE FUNCTION omega.inner_func()
RETURNS oid AS $$
DECLARE
stack text; fcesig text;
BEGIN
GET DIAGNOSTICS stack = PG_CONTEXT;
fcesig := substring(stack from 'function (.*?) line');
RETURN fcesig::regprocedure::oid;
END;
$$ LANGUAGE plpgsql;
对于来自public
模式的函数,这有点困难 - 存在不一致,并且如果没有明确附加前缀“public”,则当public
不在@987654327 中时,regprocedure
的强制转换不应该起作用@。通用解决方案需要多几行:
CREATE OR REPLACE FUNCTION omega.inner_func()
RETURNS oid AS $$
DECLARE
stack text; fcesig text; retoid oid;
BEGIN
GET DIAGNOSTICS stack = PG_CONTEXT;
fcesig := substring(stack from 'function (.*?) line');
retoid := to_regprocedure(fcesig::cstring);
IF retoid IS NOT NULL THEN RETURN retoid; END IF;
RETURN to_regprocedure(('public.' || fcesig)::cstring);
END;
$$ LANGUAGE plpgsql;
【讨论】:
“我确定你做得不好”——嗯...@Pavel 我使用了你提供的代码(谢谢!)所以要捕获我的程序的名称跑步。我在记录成功/失败信息和/或将类似信息上游传递给调用者时提供过程名称。有没有更好的方法来做到这一点?还是我做事也很糟糕? @Wellspring - 很难说 - 通常在更多模式中具有相同名称的函数是不好的。这不是典型的,然后你需要做一些非常具体的代码。另一方面,这段代码并不是很疯狂——所以还不算太糟糕。它只是不典型。来源 一些奇怪的问题可能来自其他数据库的端口,那里有一点不同的功能。但这就是生活。以上是关于PostgreSQL plpgsql 获取当前程序 oid的主要内容,如果未能解决你的问题,请参考以下文章
PostgreSQL - 继续 unique_violation (plpgsql)