Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Postgresql 在Pl/pgSQL函数中创建不冲突的临时表_Postgresql_Plpgsql - Fatal编程技术网

Postgresql 在Pl/pgSQL函数中创建不冲突的临时表

Postgresql 在Pl/pgSQL函数中创建不冲突的临时表,postgresql,plpgsql,Postgresql,Plpgsql,我想在Pl/pgSQL函数中创建一个临时表,因为我想在执行某些过程之前对它进行索引。对函数的任何并发调用都会尝试重用同一个表,这似乎是一个问题 e、 g.对函数的第一次调用创建并使用名为“test”的临时表,其数据取决于函数参数。第二个并发调用还尝试创建和使用具有相同名称但具有不同数据的临时表 医生说 “临时表在会话结束时自动删除, 或在当前事务结束时选择“ 如果使用“”ON COMMIT DROP“选项创建的临时表仅对当前事务可见,我想问题就不会存在。是这样吗 如果没有,如何从两个不同的函数调

我想在Pl/pgSQL函数中创建一个临时表,因为我想在执行某些过程之前对它进行索引。对函数的任何并发调用都会尝试重用同一个表,这似乎是一个问题

e、 g.对函数的第一次调用创建并使用名为
“test”
的临时表,其数据取决于函数参数。第二个并发调用还尝试创建和使用具有相同名称但具有不同数据的临时表

医生说

“临时表在会话结束时自动删除, 或在当前事务结束时选择“

如果使用“
”ON COMMIT DROP“
选项创建的临时表仅对当前事务可见,我想问题就不会存在。是这样吗

如果没有,如何从两个不同的函数调用自动创建独立的表


我可能会尝试创建一个临时名称,并检查是否已经存在具有此名称的表,但对我来说,这似乎需要大量管理…

临时表仅在当前会话中可见。即使并发进程共享相同的名称,它们也看不到彼此的临时表。

PostgreSQL要求每个会话为要使用的每个临时表发出自己的CREATE TEMPORATE TABLE命令。这允许不同的会话为不同的目的使用相同的临时表名(…)


不同会话的临时表不能冲突,因为每个会话都有一个专用的临时架构,仅对当前会话可见

在当前Postgres中,一次只有一个事务在同一会话中运行。因此,在同一会话中,只有两个连续的调用可以看到相同的临时对象<如您所发现的,提交删除时的代码>将临时表的生命周期限制为当前事务,避免与其他事务发生冲突

如果您(可以)拥有不随事务消亡的临时表(例如,如果您希望在当前事务结束后继续使用其中一些表),那么另一种方法是在临时表已经存在的情况下截断而不是创建临时表,这也有点便宜

包装到函数中:

CREATE OR REPLACE FUNCTION f_create_or_trunc_temp_table(_tbl text, OUT _result "char") AS
$func$
BEGIN
   SELECT INTO _result  relkind
   FROM   pg_catalog.pg_class
   WHERE  relnamespace = pg_my_temp_schema()          -- only temp objects!
   AND    relname = _tbl;

   IF NOT FOUND THEN                                  -- not found
      EXECUTE format('CREATE TEMP TABLE %I(id int)', _tbl);

   ELSIF _result = 'r' THEN                           -- table exists
      EXECUTE format('TRUNCATE TABLE %I', _tbl);      -- assuming identical table definition

   ELSE                                               -- other temp object occupies name
      RAISE EXCEPTION 'Other temp object of type >>%<< occupies name >>%<<', _result, _tbl;
      -- or do nothing, return more info or raise a warning / notice instead of an exception
   END IF;
END
$func$  LANGUAGE plpgsql;
如果表存在,则假定表定义相同。您可以做更多的工作,还可以返回更多信息,等等。这只是基本概念

相关的:


我相信您这样做是有原因的,但是在一个可以同时调用的函数中创建一个索引临时表听起来很糟糕,肯定有更好的方法来完成您想要的任务?什么是会话?两个pgAdmin查询窗口是否是两个不同的会话?当客户端建立到数据库的连接时,将启动一个单独的后端进程,该进程将处理从客户端发送的后续命令。当客户端关闭连接时,后端进程终止。这是一次会议。PgAdmin中的两个查询窗口涉及两个单独的会话。该函数似乎毫无意义,因为您总是可以
创建临时表(如果不存在…
是否应该截断它取决于特定的需要),截断一个空的临时表不需要任何费用。@klin:my函数中的查找类似于
IF NOT EXISTS
所做的查找,但要点是通过一次检查覆盖3种可能的情况。截断一个空表需要花费一些东西,即使花费很少。更重要的是,尝试截断表以外的任何内容都会引发异常。可能需要也可能不需要。此函数可以返回或发送消息。我添加了一个注释。使用简单的Postgres命令,您的函数不会产生任何没有它无法实现的效果。如果由于任何原因无法创建临时表,Postgres将引发一个错误,就像您的函数一样。由于使用了动态SQL,该函数比可能截断空表要昂贵得多。你第一次这么说。你似乎没有读我的回复。我仔细阅读了你的每一条评论。然而,我尽量避免写那些显而易见的东西。您添加了一个有点错误的注意事项,即该函数会引发异常,但它并不一定要引发异常。它绝不涉及该功能是不必要的这一事实的本质。在任何一段plpgsql代码中,您都可以捕获异常并执行其他操作。您不需要为此查询
pg_类
或执行动态SQL。
SELECT f_create_or_trunc_temp_table('my_tbl');