Cognos Content Store 缺乏原生版本控制,報表一旦誤改/誤刪無法復原。利用 Oracle 觸發器攔截 CMOBJPROPS7 表的 UPDATE/DELETE,自動保存報表定義 XML 至版本表,實現零成本版本控制。本文提供完整 DDL、遞迴路徑函數、觸發器腳本與還原操作指南。
-- 版本儲存表
CREATE TABLE cmobjversion (
modifydate DATE,
spec CLOB, -- 報表定義 XML
action VARCHAR2(32), -- 'UPDATE' 或 'DELETE'
reportpath NVARCHAR2(1000) -- 報表在 Cognos 目錄路徑
);
COMMENT ON COLUMN cmobjversion.modifydate IS '修改時間';
COMMENT ON COLUMN cmobjversion.spec IS '報表定義';
COMMENT ON COLUMN cmobjversion.action IS '動作(刪除、修改)';
COMMENT ON COLUMN cmobjversion.reportpath IS '報表存儲路徑';
CREATE OR REPLACE FUNCTION getCmObjPath (id IN NUMBER) RETURN VARCHAR2 IS
result VARCHAR2(4000);
pcmid NUMBER;
cid NUMBER := id;
cmname VARCHAR2(4000);
BEGIN
LOOP
SELECT a.pcmid, b.name
INTO pcmid, cmname
FROM cmobjects a, cmobjnames b
WHERE a.cmid = b.cmid
AND b.isdefault = 1
AND a.cmid = cid;
cid := pcmid;
result := cmname || '/' || result;
EXIT WHEN pcmid = 0;
END LOOP;
RETURN SUBSTR(result, 1, LENGTH(result)-1); -- 移除尾端 '/'
END getCmObjPath;
/
-- 邏輯:從報表 CMID 遞迴向上查詢父資料夾 (pcmid),串接名稱形成完整路徑
CREATE OR REPLACE TRIGGER cmrep_tr
BEFORE DELETE OR UPDATE ON cmobjprops7
FOR EACH ROW
BEGIN
IF :OLD.spec IS NOT NULL THEN
CASE
WHEN UPDATING THEN
INSERT INTO cmobjversion (reportpath, modifydate, spec, action)
VALUES (getCmObjPath(:OLD.cmid), SYSDATE, :OLD.spec, 'UPDATE');
WHEN DELETING THEN
INSERT INTO cmobjversion (reportpath, modifydate, spec, action)
VALUES (getCmObjPath(:OLD.cmid), SYSDATE, :OLD.spec, 'DELETE');
END CASE;
END IF;
END cmrep_tr;
/
-- 關鍵點:
-- 1. BEFORE 觸發器確保捕獲舊值 (:OLD.spec)
-- 2. 僅在 spec 非 NULL 時記錄(過濾資料夾等非報表物件)
-- 3. 使用 CASE 區分 UPDATE/DELETE 動作標記
CREATE TRIGGER、CREATE TABLE、CREATE FUNCTION 權限的用戶執行上述腳本。SELECT * FROM cmobjversion ORDER BY modifydate DESC; 應出現一筆 action='UPDATE' 記錄。action='DELETE' 記錄,spec 含完整 XML 定義。cmobjversion 找到目標版本的 spec(CLOB)。.xml,編碼設為 UTF-8。DELETE FROM cmobjversion WHERE modifydate < SYSDATE-365;(保留 1 年)。SELECT * FROM user_triggers WHERE trigger_name='CMREP_TR'; 確保 STATUS=ENABLED。ALTER TRIGGER cmrep_tr DISABLE; 避免大量寫入版本表,事後重新啟用。在 cmobjversion 增加 tenant_id、content_store_name 欄位,觸發器中從 SYS_CONTEXT('USERENV','CLIENT_IDENTIFIER') 或固定值帶入,實現隔離版本管理。
以「資料庫層觸發器 + 遞迴路徑函數 + CLOB 存儲」三件套,零代碼入侵 Cognos 應用,低成本實現企業級報表版本控制與災難恢復能力。