結構化查詢語言/臨時表
常規表是用來儲存資料較短或較長時間的容器,並將資料提供給各種程序。相反,有時需要處理短時間內且僅用於本地目的的資料。臨時表提供瞭解決方案。它們與常規表一樣,遵循 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 不受支援。