PostgreSQL中的临时表是会话级别的,即在会话结束后会自动被删除,或者可以设置为事务级别的,即在事务结束后自动被删除。也就是说不支持oracle的全局临时表的功能,除此之外,Oracle全局临时表是可以指定SCHEMA的,而PostgreSQL的临时表不能指定SCHEMA,会自动在temp临时SCHEMA中创建。
Pgtt是PostgreSQL的一个插件,可以用来兼容创建、管理和使用Oracle风格的全局临时表。
**下载地址:**https://github.com/darold/pgtt
要安装pgtt扩展插件,必须使用pg9.5以上的版本。下载完之后直接解压安装即可:
make
make install
在需要使用全局临时表的所有数据库中,使用以下命令创建扩展:
bill@bill=>create extension pgtt;
CREATE EXTENSION
我们可以手动开启/关闭该扩展,例如:
bill@bill=>SET pgtt.enabled TO off;
SET
bill@bill=>SET pgtt.enabled TO on;
SET
当我们需要使用该扩展时,首先需要使用超级用户去加载:
bill@bill=>LOAD 'pgtt';
LOAD
pgtt中相关的对象都在pgtt_schema的schema下面,该schema始终位于search_path的末尾:
bill@bill=>show search_path ;
search_path
-------------------------
bill,public,pgtt_schema
(1 row)
当我们安装完pgtt扩展后,会自动将pgtt_schema加载到search_path中。
创建全局临时表:
使用pgtt创建全局临时表的语法如下:
CREATE GLOBAL TEMPORARY TABLE test_gtt_table (
id integer,
lbl text
) ON COMMIT { PRESERVE | DELETE } ROWS;
但是需要注意:GLOBAL关键字已过时,但可以安全使用,唯一的是它将生成警告:
WARNING: GLOBAL is deprecated in temporary table creation
因此我们推荐将GLOBAL关键字进行注释使用:
CREATE /*GLOBAL*/ TEMPORARY TABLE test_gtt_table (
LIKE other_table LIKE
INCLUDING DEFAULTS
INCLUDING CONSTRAINTS
INCLUDING INDEXES
) ON COMMIT { PRESERVE | DELETE } ROWS;
例子:
建表:
bill@bill=>CREATE /*GLOBAL*/ TEMPORARY TABLE test_tt (id int, lbl text) ON COMMIT PRESERVE ROWS;
CREATE TABLE
插入数据:
bill@bill=>INSERT INTO test_tt VALUES (1, 'one'), (2, 'two'), (3, 'three');
INSERT 0 3
查看:
bill@bill=>select * from test_tt ;
id | lbl
----+-------
1 | one
2 | two
3 | three
(3 rows)
我们也可以在全局临时表上创建索引:
bill@bill=>create index idx_test on test_tt (id);
CREATE INDEX
删除表:
这里需要注意,我们不能删除正在使用的全局临时表。
bill@bill=>drop table test_tt ;
ERROR: can not drop a GTT that is in use.
要先确保被删除的表没有在被使用才能删除:
bill@bill=>SET pgtt.enabled TO off;
SET
bill@bill=>drop table test_tt ;
DROP TABLE
另外需要注意的是,我们也不能在全局临时表上使用外键和分区,尽管这些在PostgreSQL的临时表上是被允许的,但是为了兼容oracle的全局临时表,pgtt中并不允许这么使用:
CREATE GLOBAL TEMPORARY TABLE t1 (c1 integer, FOREIGN KEY (c1) REFERENCES source (id));
ERROR: attempt to create referential integrity constraint on global temporary table
尽管PostgreSQL已经支持会话级和事务级的临时表,但是不支持类似oracle的全局临时表,虽然我们可以在使用的时候通过其它方式去代替,但是对于从oracle迁移到PostgreSQL的系统来说,能够直接使用和oracle风格一致的全局临时表还是很方便的。
参考链接:
https://github.com/darold/pgtt
https://www.postgresql.org/docs/12/sql-createtable.html