首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

Oracle 10g VPD 與關聯視圖:列層級資料遮罩方案比較

     編輯:Oracle 資料庫相關知識

Oracle 10g 的虛擬私有資料庫(VPD)與傳統關聯視圖皆可實現列層級資料遮罩。本文透過薪資欄位遮罩案例,深度比較兩者在靈活性、維護性、共享池效能與應用透明度上的差異,助您選擇最適架構。

案例情境

需求:當 DEPARTMENT_ID = 60 時,遮罩 SALARY 與 COMMISSION_PCT 欄位(顯示 NULL)。

方案一:關聯視圖 + CASE 運算式

CREATE OR REPLACE VIEW MASKED_SALARY_VIEW AS
SELECT FIRST_NAME, LAST_NAME,
  CASE DEPARTMENT_ID WHEN 60 THEN NULL ELSE SALARY END AS SALARY,
  CASE DEPARTMENT_ID WHEN 60 THEN NULL ELSE COMMISSION_PCT END AS COMMISSION_PCT,
  DEPARTMENT_ID
FROM EMPLOYEES;

授權使用者僅存取視圖,不直接存取基底表。

視圖方案的擴充性瓶頸

若需求改為「使用者僅能看見自己部門的薪資」,視圖方案面臨:

  • 需為每部門建立視圖,維護負擔隨部門數線性增長
  • 使用者異動部門時,需同步調整權限
  • 查詢無法使用繫結變數,導致共享池充斥相似 SQL 副本
  • 應用程式需動態決定視圖名稱,增加複雜度

方案二:VPD 策略函數 + SYS_CONTEXT

CREATE OR REPLACE FUNCTION RLS_DEPT (OBJ_OWNER IN VARCHAR2, OBJ_NAME IN VARCHAR2)
RETURN VARCHAR2 AS
  DEPTNO NUMBER;
  PREDICATE VARCHAR2(200);
BEGIN
  DEPTNO := SYS_CONTEXT('HR_CONTEXT', 'DEPT');
  IF DEPTNO IS NULL THEN
    PREDICATE := '1=2';  -- 全部遮罩
  ELSE
    PREDICATE := 'DEPARTMENT_ID = ' || DEPTNO;
  END IF;
  RETURN PREDICATE;
END;
/

BEGIN
  DBMS_RLS.ADD_POLICY(
    OBJECT_SCHEMA => 'HR',
    OBJECT_NAME   => 'EMPLOYEES',
    POLICY_NAME   => 'DEPT_SALARY_POLICY',
    FUNCTION_SCHEMA => 'SECURITY_ADMIN',
    POLICY_FUNCTION => 'RLS_DEPT',
    SEC_RELEVANT_COLS => 'SALARY,COMMISSION_PCT',
    SEC_RELEVANT_COLS_OPT => DBMS_RLS.ALL_ROWS
  );
END;
/

VPD 核心優勢

維度關聯視圖VPD
策略集中管理分散在多個視圖單一策略函數
共享池效能多 SQL 副本單一 SQL 配合繫結變數
應用透明度需修改查詢物件名零修改,自動攔截所有存取
跨應用一致性難以保證資料庫層級強制生效
動態條件靜態、難以參數化支援 SYS_CONTEXT、SESSION 狀態

適用場景建議

  • 視圖:簡單、靜態、單一應用、欄位遮罩邏輯固定
  • VPD:多應用共享資料、動態/依上下文的安全策略、法規要求資料庫層級強制存取控制

VPD 將安全邏輯下沉至資料庫核心,實現「資料自我保護」,是企業級資料治理的優選方案。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved