5

这是我用于创建临时表的语法:

create temp table tmpTable (id bigint not null, primary key (id)) on commit drop;

我知道这意味着在每个事务结束时,该表将被删除。我的问题是,如果同一会话上的两个或多个线程创建并将值插入临时表中,它们会各自获得自己的实例还是在会话中共享临时实例?如果它是共享的,有没有办法让它每个线程都本地化?

谢谢内塔

4

1 回答 1

8

临时表对同一会话中的所有操作都是可见的。因此,在删除存在的临时表之前,您不能在同一会话中创建同名的临时表(在您的情况下提交事务)。

您可能想使用:

CREATE TEMP TABLE tmptbl IF NOT EXISTS ...

更多关于CREATE TABLE手册。


独特的临时表

要使每个“线程”(在同一会话中)的临时表本地化,您需要使用唯一的表名。一种方法是使用未绑定的SEQUENCE动态 SQL - 在 plpgsql 之类的过程语言或 DO 语句中(在不存储函数的情况下基本相同。

运行一:

CREATE SEQUENCE myseq;

利用:

DO $$
BEGIN
EXECUTE 'CREATE TABLE tmp' || nextval('myseq')  ||'(id int)';
END;
$$

要知道最新的表名:

SELECT 'tmp' || currval('myseq');

或者将其全部放入一个 plpgsql 函数中并返回表或重用表名。

但是,所有进一步的 SQL 命令都必须动态执行,因为普通 SQL 语句使用硬编码的标识符进行操作。因此,最好将其全部放入 plpgsql 函数中。


使用相同临时表的唯一 ID

另一种可能的解决方案是为同一会话中的所有线程使用相同的临时表thread_id,并向表中添加一列。如果您大量使用该功能,请务必为该列编制索引。然后使用唯一的thread_id每个线程(在同一会话中)。

只有一次:

CREATE SEQUENCE myseq;

每个线程一次:

CREATE TEMP TABLE tmptbl(thread_id int, col1 int) IF NOT EXISTS;
my_id :=  nextval('myseq'); -- in plpgsql
-- else find another way to assign unique id per thread

SQL:

INSERT INTO tmptbl(thread_id, col1) VALUES
(my_id, 2), (my_id, 3), (my_id, 4);

SELECT * FROM tmptbl WHERE thread_id = my_id;
于 2012-05-15T09:52:18.837 回答