Oracle PRAGMA RESTRICT_REFERENCES 簡易說明與測試

今天開發人員問我知不知道RESTRICT_REFERENCES()的功能,我也是第一次看到,所以到google尋找並記錄下來。

PRAGMA RESTRICT_REFERENCES(),它可以看做是對子程式做權限的控管,檢查子程式的純度(PURITY)。 可以避免例如A在DML上呼叫函式時,B因為不知情而修改該函式,雖然B在編譯上沒有問題,但是卻因為觸發到DML限制,進而導致A原本正常的DML發生錯誤。

語法:PRAGMA RESTRICT_REFERENCES(function_name | default , )RNDS, WNDS, RNPS, WNPS) | , TRUST);

RNDS,WNDS,RNPS,WNPS可以同時設定。但設定參數值為TRUST時,其它的值則全部失效。

  • function_name:應用的function

  • DEFAUT:是指應用在package的所有子程式、函式。

  • RNDS(Read No Database State):不能讀取任何資料庫的資訊,包括任何的表,連dual這個表也不行

  • RNPS(Read No Package State):不能讀取任何package的狀態資訊,如變數等。

  • WNDS(Write No Database State):不能在資料庫寫入任何資料(即不能修改表)。

  • WNPS(Write No Package State):不能向package寫入任何資訊(例如不能修改package變數的值)

  • TRUST,指出子程式是可以相信,故不受限。這個選項通常是用來PL/SQL在呼叫外部函數(如JAVA)時,因為PL/SQL是無法對外部函數進行限制。

    範例:

    create or replace package pkg_test is
      a number := 543;
      function test01 return number;
      function test02 return number;
      pragma restrict_references(test01, wnps);
      pragma restrict_references(test02, wnps);
    end;
    
    
    create or replace package body pkg_test is
    
        function test01 return number as
        begin
            a := 123;
            return a;
        end;
    
        function test02 return number as
        begin
            return a + 10 ;
        end;
    
        function test03 return number as
            b number ;
        begin
            b := 123;
            return b;
        end;
        
        function test04 return number as
        begin
            a := 9999;
            return a;
        end;
        
    end pkg_test;
    

    test01變更了package的變數a的值,故編譯錯誤:PLS-00452: Subprogram 'TEST01' violates its associated pragma

    test02只使用變數值,故未被限制;

    test03則未使用到package的變數,而是使用function內部的變數,所以未被限制住

    test04因為未定義restrict_references,故可以變更a的值