Oracle

如何檢測在哪個模式中呼叫了過程?

  • October 15, 2014

我正在努力解決 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_USERAUTHID DEFINER(預設時沒有定義)。

  • UsingAUTHID CURRENT_USER從呼叫過程的模式中獲取權限,因此 CURRENT_USER 命令返回的是發出過程的模式,而不是儲存它的模式。
  • 使用AUTHID DEFINER(如果您不指定任何內容,則預設)不會從呼叫該過程的模式中獲得權限,因此 CURRENT_USER 命令報告包含該過程的模式。

您可以使用 Oraclesowa_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將保存過程的名稱而不是包名稱。

引用自:https://dba.stackexchange.com/questions/80235