结构化查询语言/临时表
常规表是用来存储数据较短或较长时间的容器,并将数据提供给各种进程。相反,有时需要处理短时间内且仅用于本地目的的数据。临时表提供了解决方案。它们与常规表一样,遵循 SQL 语法。
所有临时表的共同特征是,每个会话(连接)都会获得临时表的独立副本,而不会对其他会话产生任何副作用。这会导致每个会话只能看到之前插入的数据。数据在不同会话之间不会共享,即使它们在同一时间使用相同的表名。每个会话都在不同的副本上进行操作。另一个共同特征是,当会话终止时,临时表的所有数据都会自动被丢弃。不需要显式 DELETE 或 DROP TABLE。
临时表的概念类似于编程语言中记录数组的概念。它相对于数组的优势是可以使用 SQL 中所有已知的 DML 语句,例如:如果您需要一些中间数据,您可以从常规表中检索它并使用一个 Insert+Subselect 命令将其存储在临时表中。它相对于常规表的优势是,可以节省日志记录和锁定的开销。
临时表有三种略微不同的类型
- 全局临时表
- 本地临时表
- 声明式本地临时表。
CREATE GLOBAL TEMPORARY TABLE <table_name> (...) [ ON COMMIT { PRESERVE | DELETE } ROWS ];
CREATE LOCAL TEMPORARY TABLE <table_name> (...) [ ON COMMIT { PRESERVE | DELETE } ROWS ];
DECLARE LOCAL TEMPORARY TABLE <table_name> (...) [ ON COMMIT { PRESERVE | DELETE } ROWS ];
如果使用短语“ON COMMIT DELETE ROWS”,则数据会在每次 COMMIT 命令执行时自动被丢弃,否则会在会话结束时(或使用 DELETE 命令)被丢弃。
如果创建 GTT,它的定义将成为数据库的一部分,即使在定义会话结束之后也是如此。使用数据库的其他会话将看到此表定义作为架构的一部分。GTT 可以与常规表同时定义。应用程序可以使用现有的 GTT 或创建自己的 GTT。到目前为止,GTT 与常规表没有区别。区别在于数据。与所有临时表一样,每个会话都会获得表的独立副本,并且无法访问其他会话的数据。如果会话终止,表中的所有数据都会自动被丢弃。
一个典型的用例是一个应用程序,它需要一个关于自身活动的临时协议,例如成功操作、异常等,以便稍后执行恢复活动。这些信息对其他会话来说并不重要。此外,它可以在事务结束时或会话结束时被删除。
另一个用例是一个应用程序,它存储一个中间结果集,并迭代该结果集的行以根据列值执行操作。
-- The table may be defined by a different session long time before.
CREATE GLOBAL TEMPORARY TABLE temp1 (
ts TIMESTAMP,
action CHAR(100),
state CHAR(50)
)
ON COMMIT PRESERVE ROWS;
--
-- Insert some data
INSERT INTO temp1 VALUES (current_timestamp, 'node-1-request sended.', 'OK');
INSERT INTO temp1 VALUES (current_timestamp, 'node-2-request sended.', 'OK');
INSERT INTO temp1 VALUES (current_timestamp, 'node-1-answer received.', 'Failed');
INSERT INTO temp1 VALUES (current_timestamp, 'node-2-answer received.', 'OK');
SELECT count(*) FROM temp1 WHERE state = 'OK';
...
COMMIT;
SELECT count(*) FROM temp1; -- In this example, all rows should have survived the COMMIT command
-- After a disconnect from the database and establishing a new session the table exists and is empty.
LTT 的定义永远不会超过会话的持续时间。同样适用于它的数据,这与所有临时表的行为一致。因此,每个会话都必须在存储任何数据之前定义自己的 LTT。多个会话可以同时使用相同的表名,而不会相互影响,这再次与所有临时表的行为一致。
-- The table must be defined by the same session (connection), which stores data into it.
CREATE LOCAL TEMPORARY TABLE temp2 (
ts TIMESTAMP,
action CHAR(100),
state CHAR(50)
)
ON COMMIT PRESERVE ROWS;
-- After a disconnect from the database and establishing a new session, the table will not exist.
SQL 标准区分 SQL 会话和 SQL 会话内的模块。它规定 LTT 只能在创建表的模块内可见。这些表不会在同一 SQL 会话的不同模块之间共享。但是 LTT 的定义会出现在 DBMS 的信息模式中。
DLTT 的主要概念与 LTT 非常相似。区别在于,与 LTT 的定义相反,DLTT 的定义不会出现在 DBMS 的信息模式中。它只被定义它的模块所知。可以将 DLTT 想象成某种模块局部变量。
-- The declaration must be defined by the same module which stores data into the table.
DECLARE LOCAL TEMPORARY TABLE temp3 (
ts TIMESTAMP,
action CHAR(100),
state CHAR(50)
)
ON COMMIT PRESERVE ROWS;
-- After a disconnect from the module and entering the module again, the declaration will not exist.
MySQL
- 省略关键字 LOCAL/GLOBAL 和 ON COMMIT 短语。临时表始终是 LOCAL,并且 ON COMMIT 始终以 PRESERVE ROWS 的方式工作。
- GTT 和 DLTT 不受支持。
Oracle
- LTT 和 DLTT 不受支持。