一個地理實體從誕生到消亡在時空中的完整軌跡。對應 (x, y, t) 三維空間(或三維實體 + 時間 = 四維)。屬性資訊儲存為一張二維表,每列代表一個時間切面的屬性。
時空物件在特定時刻的空間範圍與屬性記錄。如:飯店在 2020-01-01 的位置、面積、營業狀態。快照屬性對應時空物件屬性表中的一筆記錄。
PL/SQL Package 變數在 Session 層級隔離,適合儲存「當前觀察時間」等上下文參數,不影響其他 Session。
-- 快照記錄表
CREATE TABLE spatio_temporal_snapshots (
obj_id NUMBER,
snap_time TIMESTAMP, -- 快照生效時間
snap_end TIMESTAMP, -- 快照失效時間 (下一個快照的時間)
geom SDO_GEOMETRY, -- 空間幾何
attr_json CLOB -- 屬性 JSON 或關聯屬性表 FK
);
-- 封裝:設定/取得觀察時間、可見性判斷
CREATE OR REPLACE PACKAGE pkg_temporal_ctx IS
PROCEDURE set_obs_time(p_time TIMESTAMP);
FUNCTION get_obs_time RETURN TIMESTAMP;
FUNCTION snap_filter(p_snap_time TIMESTAMP, p_snap_end TIMESTAMP) RETURN NUMBER;
END;
/
CREATE OR REPLACE PACKAGE BODY pkg_temporal_ctx IS
g_obs_time TIMESTAMP;
PROCEDURE set_obs_time(p_time TIMESTAMP) IS BEGIN g_obs_time := p_time; END;
FUNCTION get_obs_time RETURN TIMESTAMP IS BEGIN RETURN g_obs_time; END;
-- 判斷快照在觀察時間是否可見
FUNCTION snap_filter(p_snap_time TIMESTAMP, p_snap_end TIMESTAMP) RETURN NUMBER IS
BEGIN
IF p_snap_time IS NULL THEN RETURN 0; END IF;
IF g_obs_time IS NULL THEN RETURN 0; END IF; -- 未設定觀察時間預設不可見
IF p_snap_time <= g_obs_time AND (p_snap_end IS NULL OR p_snap_end > g_obs_time) THEN
RETURN 1; -- 可見
END IF;
RETURN 0;
END;
END;
/
-- 動態視圖:自動過濾可見快照
CREATE OR REPLACE VIEW v_current_snapshots AS
SELECT obj_id, snap_time, geom, attr_json
FROM spatio_temporal_snapshots
WHERE pkg_temporal_ctx.snap_filter(snap_time, snap_end) = 1;
CREATE OR REPLACE TRIGGER trg_v_current_snapshots_iu
INSTEAD OF INSERT OR UPDATE ON v_current_snapshots
FOR EACH ROW
DECLARE
v_obs_time TIMESTAMP := pkg_temporal_ctx.get_obs_time();
BEGIN
IF INSERTING THEN
-- 新增即建立新快照,snap_time = 觀察時間,關閉前一個快照
UPDATE spatio_temporal_snapshots
SET snap_end = v_obs_time
WHERE obj_id = :NEW.obj_id AND snap_end IS NULL;
INSERT INTO spatio_temporal_snapshots(obj_id, snap_time, snap_end, geom, attr_json)
VALUES (:NEW.obj_id, v_obs_time, NULL, :NEW.geom, :NEW.attr_json);
ELSIF UPDATING THEN
-- 更新當前可見快照
UPDATE spatio_temporal_snapshots
SET geom = :NEW.geom, attr_json = :NEW.attr_json
WHERE obj_id = :OLD.obj_id AND snap_time = :OLD.snap_time;
END IF;
END;
/
插入新快照時,必須將該物件前一個 snap_end IS NULL 的記錄更新為新快照的 snap_time,確保時間軸連續、無重疊、無間隙。需在交易中原子完成。
| 模式 | 參數 | snap_filter 邏輯 | 用途 |
|---|---|---|---|
| 當前狀態 (預設) | 單一觀察時間點 | snap_time ≤ obs_time < snap_end | 日常業務查詢 |
| 歷史追溯 | 目標物件 ID | obj_id = target_id (忽略時間) | 單一物件完整變遷 |
| 時段觀察 | 起始/結束時間 | 回傳 1=時段內首筆, 2=時段內末筆, 4=中間 | 兩時間點比對、動畫播放 |
實現方式:Package 新增 set_obs_mode、get_obs_mode,snap_filter 依模式分支。
CREATE TABLE temporal_object_relations (
obj_id_1 NUMBER,
obj_id_2 NUMBER,
relation_type VARCHAR2(20), -- 'EVOLVE'演變, 'MERGE'融合, 'SPLIT'分裂, 'RELATE'關聯
relation_time TIMESTAMP,
description VARCHAR2(200)
);
-- 查詢當前狀態 (觀察時間 = 系統時間)
BEGIN pkg_temporal_ctx.set_obs_time(SYSTIMESTAMP); END;
SELECT * FROM v_current_snapshots WHERE obj_id = 1001;
-- 查詢歷史 (2023-01-01 狀態)
BEGIN pkg_temporal_ctx.set_obs_time(TIMESTAMP '2023-01-01 00:00:00'); END;
SELECT * FROM v_current_snapshots WHERE obj_id = 1001;
-- 歷史追溯模式
BEGIN pkg_temporal_ctx.set_obs_mode('HISTORY'); pkg_temporal_ctx.set_target_obj(1001); END;
SELECT * FROM v_current_snapshots; -- 見該物件所有快照
snap_time ≥ snap_end、禁止時間倒退、禁止重疊區間。CREATE INDEX idx_snap_obj_time ON spatio_temporal_snapshots(obj_id, snap_time); 加速版本查詢。snap_time 範圍分區,提升歷史查詢效能。