如何檢測在哪個模式中呼叫了過程?
我正在努力解決 Oracle 12.1 中有關程序的問題。
我們正在使用基於模式的數據隔離方法。我們使用一個模式作為 PUBLIC,每個項目都有完全相同的表和過程,但數據不同。
問題: 我需要獲取呼叫過程的模式名稱,以便更新包含所有不同模式的 PUBLIC 模式中的表的行。
標頭定義
CREATE OR REPLACE PACKAGE PKG_DONE AUTHID DEFINER AS PROCEDURE ACK_FROM_WEB(UUID INTERNAL.UUID%TYPE, USERNAME PUBLIC.USERS.USER_NAME%TYPE); END PKG_DONE;
車身定義
CREATE OR REPLACE PACKAGE BODY PKG_DONE AS PROCEDURE ACK_FROM_WEB(P_UUID INTERNAL.UUID%TYPE, P_USERNAME PUBLIC.USERS.USER_NAME%TYPE) AS BEGIN INSERT INTO ACK_WEB_USER(UUID,USERNAME) VALUES (P_UUID,P_USERNAME); UPDATE PUBLIC.ACK_CONFIRMATIONS SET ASSIGNED = P_USERNAME WHERE UUID = P_UUID AND SCHEMA_NAME = USER; END ACK_FROM_WEB; END PKG_DONE;
它在我們的網站上完美執行,因為我們在操作時設置了與 SCHEMA 的會話,但現在我們需要通過電子郵件進行外部確認,並且出於安全原因,它僅適用於 PUBLIC 模式。我想檢索我在語句中呼叫過程而不是 USER 的架構
UPDATE PUBLIC.ACK_CONFIRMATIONS SET ASSIGNED = P_USERNAME WHERE UUID = P_UUID AND SCHEMA_NAME = USER;
。是否有任何命令/dbms 程序或任何我可以得到它的東西?
找到解決方案。
經過一番研究,我找到了一個很好的例子,說明如何通過 dual 找到目前使用者。解決方案非常簡單,只需添加
select sys_context( 'userenv', 'current_user' ) into user_name from dual;
使用者 user_name 而不是 user。身體看起來如下
CREATE OR REPLACE PACKAGE BODY PKG_DONE AS PROCEDURE ACK_FROM_WEB(P_UUID INTERNAL.UUID%TYPE, P_USERNAME PUBLIC.USERS.USER_NAME%TYPE) AS user_name VARCHAR2(255 CHAR); BEGIN select sys_context( 'userenv', 'current_user' ) into user_name from dual; INSERT INTO ACK_WEB_USER(UUID,USERNAME) VALUES (P_UUID,P_USERNAME); UPDATE PUBLIC.ACK_CONFIRMATIONS SET ASSIGNED = P_USERNAME WHERE UUID = P_UUID AND SCHEMA_NAME = user_name; END ACK_FROM_WEB; END PKG_DONE;
長解釋:
程序可以有
AUTHID CURRENT_USER
或AUTHID DEFINER
(預設時沒有定義)。
- Using
AUTHID CURRENT_USER
從呼叫過程的模式中獲取權限,因此 CURRENT_USER 命令返回的是發出過程的模式,而不是儲存它的模式。- 使用
AUTHID DEFINER
(如果您不指定任何內容,則預設)不會從呼叫該過程的模式中獲得權限,因此 CURRENT_USER 命令報告包含該過程的模式。
您可以使用 Oracles
owa_util
包的功能之一,名為WHO_CALLED_ME
.為了展示這個特性,我們可以創建一個表來儲存對 Oracle 過程的呼叫結果。
create table T_CALLSTACK ( OWNER_NAME varchar2(30), OBJECT_NAME varchar2(30), LINE_NUMBER number, CALLER_INFO varchar2(100), INSERTDATE date );
作為將插入一些值的測試程序,我們使用:
create or replace procedure P_CALLED_BY_T is v_Owner varchar2(30); v_PackageName varchar2(30); v_LineNumber number; v_CallerT varchar2(100); begin owa_util.WHO_CALLED_ME (v_Owner, v_PackageName, v_LineNumber, v_CallerT); -- v_Owner will contain the schema name of the procedure which -- called this procedure itself insert into T_CALLSTACK (OWNER_NAME, OBJECT_NAME, LINE_NUMBER, CALLER_INFO, INSERTDATE) values (v_Owner, v_PackageName, v_LineNumber, v_CallerT, sysdate); end P_CALLED_BY_T;
該過程
WHO_CALLED_ME
將返回架構的名稱以及呼叫包體內的包名稱和行號,caller-T是呼叫我們自定義過程的數據庫對象的類型P_CALLED_BY_T
。如果呼叫者本身只是一個過程,則該變數v_PackageName
將保存過程的名稱而不是包名稱。