關於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
定義存儲過程時,通過指定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;
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;
/*********************************
名稱: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;