跳轉到內容

結構化查詢語言/臨時表

來自華夏公益教科書,開放的書籍,面向開放的世界



常規表是用來儲存資料較短或較長時間的容器,並將資料提供給各種程序。相反,有時需要處理短時間內且僅用於本地目的的資料。臨時表提供瞭解決方案。它們與常規表一樣,遵循 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。到目前為止,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 的定義永遠不會超過會話的持續時間。同樣適用於它的資料,這與所有臨時表的行為一致。因此,每個會話都必須在儲存任何資料之前定義自己的 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)

[編輯 | 編輯原始碼]

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 不受支援。


華夏公益教科書