資料庫表格中常使用數值序列,無論是自然產生的業務流水號,還是由 Oracle Sequence 物件分配的代理鍵,其核心目的皆為賦予每一筆資料唯一且遞增的身分識別。然而,在實際操作過程中,序列間隙(Gap)的產生卻在所難免。例如,預存程序從 Sequence 取得數值存入區域變數卻未實際使用,該數值便永久流失,無法歸還 Sequence,導致序列出現斷號。
雖然關聯式資料庫模型不強制要求序列連續無縫,但業務稽核或法規遵循往往需要追蹤缺失號碼。傳統做法多採用 PL/SQL 迴圈逐行比對,或是撰寫複雜的自我聯結(Self-Join)語句,前者效能低落,後者程式碼難以維護。
Oracle 解析函數提供了更優雅、高效的集合式解決方案。透過 LAG 或 LEAD 函數,我們能在單一 SQL 查詢中,同時存取當前列與前一列(或後一列)的值,輕鬆識別間隙。
解析函數的標準語法如下:
{LEAD | LAG} (value_expression, offset, default) OVER ([PARTITION BY expr] ORDER BY expr)
假設有一張 sensor_log 表,記錄自動感測器產生的測量序號 measure_id。我們要找出是否有編號遺失。
WITH aquery AS (
SELECT
measure_id AS after_gap,
LAG(measure_id, 1, 0) OVER (ORDER BY measure_id) AS before_gap
FROM sensor_log
WHERE measure_id > 0 -- 排除第一行的預設值 0
)
SELECT before_gap, after_gap
FROM aquery
WHERE after_gap - before_gap > 1
ORDER BY before_gap;
aquery,包含當前行 after_gap 與前一行 before_gap 的序號。LAG(measure_id, 1, 0) 取得前一列的 measure_id,第一列無前驅時回傳 0。WHERE measure_id > 0 移除第一列產生的虛假間隙(0 → 首號)。after_gap - before_gap > 1,表示兩者之間存在至少一個缺號。此法僅需單一掃描,無需迴圈或自我聯結,效能大幅優於傳統寫法,且程式碼簡潔易讀,極適合大量資料環境下的間隙稽核作業。