Oracle存儲過程動態創建臨時表/存儲過程執行權限問題--AUTHID CURRENT_USER


 

 

關於Oracle存儲過程執行權限問題的解決

http://blog.sina.com.cn/s/blog_6ceed3280101hvlo.html

(2014-04-02 04:06:28)

  分類: oracle-基礎
    今天晚上升級,有個存儲過程死活編譯不過去,提示權限不足,但是用戶是具有dba權限的,網上一查才知道, oracle存儲過程分兩種,DR(Definer's Rights ) Procedure和IR(Invoker's Rights ) Procedure。
    1、定義者權限:定義者權限PL/SQL程序單元是以這個程序單元擁有者的特權來執行它的,也就是說,任何具有這個PL/SQL程序單元執行權的用戶都可 以訪問程序中的對象。所有具有執行權的用戶都有相同的訪問權限,在定義者權限下,執行的用戶操作的schema為定義者,所操作的對象是定義者在編譯時指 定的對象。在定義者(definer)權限下,當前用戶的權限為角色無效情況下所擁有的權限。
    2、調用者權限:調用者權限是指當前用戶(而不是程序的創建者)執行PL/SQL程序體的權限。這意味着不同的用戶對於某個對象具有的權限很可能是不同 的,這個思想的提出,解決了不同用戶更新不同表的方法。在調用者權限下,執行的用戶操作的schema為當前用戶,所操作的對象是當前模式下的對象。在調 用者(invoker)權限下,當前用戶的權限為當前所擁有的權限(含角色)。
    3、ORACLE默認為定義者權限,定義者權限在存儲過程中ROLE無效,需要顯示授權,例如在存儲過程中調用其他用戶的表,但是定義存儲過程的當前用戶沒有顯示訪問該表的權限,即使當前用戶具有dba角色,編譯過程中也會出現權限不足的問題,因為role無效。
    定義存儲過程時,通過指定AUTHID 屬性,定義DR Procedure 和IR Procedure
DR Procedure 
1、定 義
    CREATE OR REPLACE procedure DEMO(ID in NUMBER) AUTHID DEFINER as
      ...
    BEGIN
      ...
    END DEMO;
IR Procedure
1、定 義
    CREATE OR REPLACE procedure DEMO(ID in NUMBER) AUTHID CURRENT_USER as
     ...
    BEGIN
     ...
    END DEMO;
 

用存儲過程創建數據表:

創建時注意必須添加authid current_user ,如果創建的表已存在,存儲過程繼續執行,但如不不加此關鍵語句,存儲過程將出現異常,

這個語句相當於賦權限。
 
我的實例:SP1 call SP 2:
1. SP1:
CREATE OR REPLACE Procedure Proc_Update_ID_NO ( v_IN in Varchar2, v_OUT Out Varchar2) AUTHID CURRENT_USER
As

v_sqlerrm VARCHAR2(4000) ;
v_temp_table varchar(30);

Begin

-- DELETE DUPLICATE DATA FROM table CAR.ZCXYXX_SZJSPX,KEEP THE LATEST ONE RECORD.
--CALL SP  Proc_DISTINCT_ZCXYXX_SZJSPX('TEMP_ZCXYXX_SZJSPX')
v_temp_table:='TEMP_ZCXYXX_SZJSPX';

 -- Call SP to delete duplicate records      
 Proc_DISTINCT_ZCXYXX_SZJSPX(v_temp_table);
    
 
  MERGE INTO DRIVER_TRAIN_LOG Target USING
  (
        SELECT DISTINCT
               DRIVER_NO               ,--學員流水號
               ID_NO                   ,--身份證明號碼
               TRAIN_CAR_CLASS          --申請車型(准駕車型
        FROM  ZCXYXX_SZJSPX
  ) Source
  ON
  (
       Source.DRIVER_NO       = Target.DRIVER_NO     --  AND
      -- Source.TRAIN_CAR_CLASS = Target.TRAIN_CAR_CLASS
  )
  WHEN MATCHED THEN  UPDATE  SET
               Target.ID_NO      = Source.ID_NO ;
               --Target.TRAIN_CAR_CLASS = Source.TRAIN_CAR_CLASS ;

   COMMIT;  --1
   
   /* UPDATE TRAIN_CAR_CLASS */
    MERGE INTO ZCXYXX_SZJSPX Target USING
    (
          SELECT DISTINCT
                 ID_NO                   ,--身份證明號碼
                 TRAIN_CAR_CLASS          --申請車型(准駕車型
          FROM  DRIVER_TRAIN_LOG
    ) Source
    ON
    (
         Source.ID_NO      = Target.ID_NO
    )
    WHEN MATCHED THEN  UPDATE  SET
                 Target.TRAIN_CAR_CLASS      = Source.TRAIN_CAR_CLASS ;

   COMMIT;

   EXCEPTION
   WHEN OTHERS THEN
        v_sqlerrm := sqlcode|| SQLERRM|| '存儲過程[Proc_Update_ID_NO]執行失敗!';
        RAISE_APPLICATION_ERROR(-20003,v_sqlerrm);

   ROLLBACK;


   v_OUT := v_sqlerrm ;

End Proc_Update_ID_NO;
 
----------------------
SP2:
create or replace procedure Proc_DISTINCT_ZCXYXX_SZJSPX(IN_TABLE_NAME varchar2) AUTHID CURRENT_USER  as
  /*********************************
名稱:Proc_DISTINCT_ZCXYXX_SZJSPX
功能描述:創建臨時數據存儲表

修訂記錄:
版本號   編輯時間  編輯人  修改描述
1.0.0    2015-9-20  **  1.創建此存儲過程
1.0.1    2015-9-21  **  2.修改表名稱及變量名稱,增加必要注釋

存儲過程執行權限問題: AUTHID CURRENT_USER

入參出參描述:
IN_TABLE_NAME 要創建的臨時表名
**********************************/
      v_tablename varchar2(30);--表名
      v_flag number(10,0);
      v_sqlfalg varchar(200);
      v_create_sql varchar(4000);
begin
      v_flag:=0;
      v_tablename:=UPPER(IN_TABLE_NAME);
      v_sqlfalg:='select count(*) from user_TABLES where table_name='''||v_tablename||'''';
      v_create_sql:='CREATE TABLE '|| v_tablename ||' AS SELECT * from
(  select DRIVER_NO,ID_NO,NAME,TRAIN_CAR_CLASS,ACCEPT_DATE,REGIST_STATUS,OPERATION, rec_update_date,MEMO,
   row_number() over (partition BY ID_NO order by rec_update_date desc) RN from ZCXYXX_SZJSPX WHERE RN=1)' ;
     -- dbms_output.put_line(v_create_sql);
      
      execute immediate v_sqlfalg into v_flag;
      if v_flag=0 then  --如果沒有這個表 則去創建
        begin
            -- DELETE DUPLICATE DATA FROM table CAR.ZCXYXX_SZJSPX,KEEP THE LATEST ONE RECORD.
            execute immediate v_create_sql;
            execute immediate 'DROP TABLE ZCXYXX_SZJSPX';
            execute immediate 'ALTER TABLE TEMP_ZCXYXX_SZJSPX rename TO ZCXYXX_SZJSPX';
         end;
       else
         execute immediate 'DROP TABLE TEMP_ZCXYXX_SZJSPX';
            -- DELETE DUPLICATE DATA FROM table CAR.ZCXYXX_SZJSPX,KEEP THE LATEST ONE RECORD.
            execute immediate v_create_sql;
            execute immediate 'DROP TABLE ZCXYXX_SZJSPX';
            execute immediate 'ALTER TABLE TEMP_ZCXYXX_SZJSPX rename TO ZCXYXX_SZJSPX';
      end if;


   EXCEPTION
   WHEN OTHERS THEN
        --dbms_output.put_line( SQLCODE|| ' :'|| SQLERRM);
        RAISE_APPLICATION_ERROR(-20003,SQLCODE|| SQLERRM|| '存儲過程[Proc_DISTINCT_ZCXYXX_SZJSPX]執行失敗');
   ROLLBACK;
end;
 
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM