首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> Oracle 資料庫 >> Oracle 資料庫基礎

Oracle 10g VPD 列層級遮罩 vs 關聯視圖:深度比較

     編輯:Oracle 資料庫基礎

案例需求

當 DEPARTMENT_ID = 60 時遮罩 SALARY、COMMISSION_PCT 欄位。

方案一:關聯視圖

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;

透過 GRANT SELECT ON masked_salary_view TO hr_user 控制存取。

方案二:VPD (Virtual Private Database)

-- 1. 建立 Context 保存使用者部門
CREATE CONTEXT hr_context USING hr_pkg;

-- 2. 策略函數
CREATE OR REPLACE FUNCTION rls_dept (
  obj_owner IN VARCHAR2,
  obj_name  IN VARCHAR2
) RETURN VARCHAR2 IS
  v_deptno NUMBER;
  v_pred   VARCHAR2(200);
BEGIN
  v_deptno := SYS_CONTEXT('HR_CONTEXT', 'DEPT');
  IF v_deptno IS NULL THEN
    v_pred := '1=2'; -- 全部遮罩
  ELSE
    v_pred := 'department_id = ' || v_deptno;
  END IF;
  RETURN v_pred;
END;
/

-- 3. 掛載策略
BEGIN
  DBMS_RLS.ADD_POLICY(
    object_schema   => 'HR',
    object_name     => 'EMPLOYEES',
    policy_name     => 'DEPT_MASK_POLICY',
    function_schema => 'HR',
    policy_function => 'RLS_DEPT',
    statement_types => 'SELECT',
    sec_relevant_cols => 'SALARY,COMMISSION_PCT', -- 僅遮罩特定欄位
    sec_relevant_cols_opt => DBMS_RLS.ALL_ROWS    -- 10g: 顯示所有列但敏感欄位為 NULL
  );
END;
/

核心差異比較

維度關聯視圖VPD
實作複雜度低中高
動態條件靜態,需建多個視圖動態,單一策略函數支援任意邏輯
共用池效率每視圖一份游標單一游標,SYS_CONTEXT 為繫結變數
應用程式修改需改查詢視圖名零修改,透明攔截所有存取
多應用共存難以統一原生支援,所有連線自動受保護
欄位級遮罩需在視圖列出所有欄位SEC_RELEVANT_COLS 精確指定

關鍵優勢:VPD 的透明性

VPD 修飾的是 基礎表,無論透過何種應用、報表工具、Ad-hoc 查詢存取 EMPLOYEES,策略自動生效。視圖僅保護透過該視圖的存取,繞過視圖即可看到原始資料。

效能考量

  • 策略函數應極簡單,避免複雜查詢。
  • 善用 SYS_CONTEXT 而非查詢表格取得條件值。
  • 12c+ 可使用 DBMS_RLS.ADD_POLICY(..., policy_type => DBMS_RLS.CONTEXT_SENSITIVE) 快取策略結果。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved