Postgresql 在Pl/pgSQL函数中创建不冲突的临时表
我想在Pl/pgSQL函数中创建一个临时表,因为我想在执行某些过程之前对它进行索引。对函数的任何并发调用都会尝试重用同一个表,这似乎是一个问题 e、 g.对函数的第一次调用创建并使用名为Postgresql 在Pl/pgSQL函数中创建不冲突的临时表,postgresql,plpgsql,Postgresql,Plpgsql,我想在Pl/pgSQL函数中创建一个临时表,因为我想在执行某些过程之前对它进行索引。对函数的任何并发调用都会尝试重用同一个表,这似乎是一个问题 e、 g.对函数的第一次调用创建并使用名为“test”的临时表,其数据取决于函数参数。第二个并发调用还尝试创建和使用具有相同名称但具有不同数据的临时表 医生说 “临时表在会话结束时自动删除, 或在当前事务结束时选择“ 如果使用“”ON COMMIT DROP“选项创建的临时表仅对当前事务可见,我想问题就不会存在。是这样吗 如果没有,如何从两个不同的函数调
“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;
如果表存在,则假定表定义相同。您可以做更多的工作,还可以返回更多信息,等等。这只是基本概念
相关的:
创建临时表(如果不存在…
是否应该截断它取决于特定的需要),截断一个空的临时表不需要任何费用。@klin:my函数中的查找类似于IF NOT EXISTS
所做的查找,但要点是通过一次检查覆盖3种可能的情况。截断一个空表需要花费一些东西,即使花费很少。更重要的是,尝试截断表以外的任何内容都会引发异常。可能需要也可能不需要。此函数可以返回或发送消息。我添加了一个注释。使用简单的Postgres命令,您的函数不会产生任何没有它无法实现的效果。如果由于任何原因无法创建临时表,Postgres将引发一个错误,就像您的函数一样。由于使用了动态SQL,该函数比可能截断空表要昂贵得多。你第一次这么说。你似乎没有读我的回复。我仔细阅读了你的每一条评论。然而,我尽量避免写那些显而易见的东西。您添加了一个有点错误的注意事项,即该函数会引发异常,但它并不一定要引发异常。它绝不涉及该功能是不必要的这一事实的本质。在任何一段plpgsql代码中,您都可以捕获异常并执行其他操作。您不需要为此查询pg_类
或执行动态SQL。
SELECT f_create_or_trunc_temp_table('my_tbl');