如何在PostgreSQL中创建一个临时函数?


82

我必须在数据库中执行循环。这只是一个时间要求。执行完函数后,我现在要删除函数。

有什么好的方法可以创建临时/一次性功能?

Answers:


115

我需要知道如何在编写的脚本中多次使用。事实证明,您可以使用pg_temp模式创建一个临时函数。这是根据您的连接需求创建的架构,是存储临时表的位置。当您的连接关闭或过期时,此架构将被删除。事实证明,如果您在此架构上创建函数,该架构将自动创建。因此,

create function pg_temp.testfunc() returns text as 
$$ select 'hello'::text $$ language sql;

只要您保持连接状态,该功能就会一直存在。无需调用放置命令。


61

@crowmagnumb的答案中有关智能技巧的一些附加说明

  • 根据汤姆·莱恩Tom Lane)的说法,该功能必须始终为架构合格,即使该功能pg_temp已存在search_path(如默认情况下一样),以防止特洛伊木马:
CREATE FUNCTION pg_temp.f_inc(int)
  RETURNS int AS 'SELECT $1 + 1' LANGUAGE sql IMMUTABLE;

SELECT pg_temp.f_inc(42);
f_inc
-----
43
  • 在临时模式中创建的函数仅在同一会话内可见(就像临时表一样)。所有其他会话都看不到它(即使是同一角色)。您可以在之后的同一会话中以不同角色访问该功能SET ROLE

  • 您甚至可以基于此“临时”功能创建功能索引:

    CREATE INDEX foo_idx ON tbl (pg_temp.f_inc(id));
    

    从而在非临时表上使用临时函数创建普通索引。这样的索引对于所有会话都是可见的,但仅对创建会话有效。查询计划器将不使用功能索引,该功能索引不会在查询中重复。仍然是一个肮脏的把戏。会话关闭时,它将作为依赖对象自动删除。完全不应允许这样的感觉...


如果您只需要重复执行一个函数,而只需要SQL,则考虑准备一条语句。它的行为很像在会话结束时终止的临时SQL函数。但是,它不是同一件事,并且只能与一起使用EXECUTE,不能嵌套在另一个查询中。例:

PREPARE upd_tbl AS
UPDATE tbl t SET set_name = $2 WHERE tbl_id = $1;

呼叫:

EXECUTE upd_tbl(123, 'foo_name');

细节:


30

如果您使用的是9.0版,则可以使用新的DO语句执行此操作:

http://www.postgresql.org/docs/current/static/sql-do.html

在以前的版本中,您需要创建函数,调用它并再次将其删除。


4
...它对于在终端上编写脚本很有用,但是您不能像“匿名函数”(或lambda)那样再次调用它,因此DO语句不如“临时函数”有用。
彼得·克劳斯

@PeterKrauss:如果要再次调用它,则需要创建一个实函数。
a_horse_with_no_name 2014年

当然,我的a_hourse :-)我只是展示了实现“临时”的理论路径。这就是为什么对于主要问题更好的答案(对于PostgreSQL可能是)pg_temp.foo()。我不明白为什么在2014年今天(!?)具有如此简单和如此快速的示例(例如Lua)SQL DML语言无法提供lambda函数(!)。
彼得·克劳斯

7
另外,DO与函数相反,语句不能具有输入参数,也不能返回结果。
DanielVérité15年

2
如果它不返回,我们应该称它为“函数”吗?
AndreKR

-4

对于Ad Hock过程,游标还不错。但是,它们对于生产使用而言效率太低。

它们将使您轻松地在db中循环执行sql结果。


6
为什么您认为PostgreSQL中的游标效率低下?
Frank Heikens 2011年

2
游标在循环时保持数据库连接。带有数百个长时间运行的游标的网页将使连接匮乏,并使站点/数据库屈服。
拜伦·惠特洛克
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.