Oracle 패키지에 모든 예외를 기록하는 방법은 무엇입니까?
모든 예외를 Oracle 패키지에 기록하려고 합니다.다음은 절차의 마지막 부분입니다.
EXCEPTION
WHEN OTHERS THEN
INSERT INTO VSLogger (MESSAGE) VALUES ('Caught Exception');
이것은 잘 작동하지만 오류 코드와 메시지도 기록하고 싶습니다.시도해 봤습니다.
EXCEPTION
WHEN OTHERS THEN
INSERT INTO VSLogger (MESSAGE) VALUES ('Caught Exception: Error ' || SQLCODE || ', Msg: ' || SQLERRM);
하지만 이것은 나에게 오류를 줍니다.
490/7 PL/SQL: SQL Statement ignored
490/100 PL/SQL: ORA-00984: column not allowed here
이것을 하는 올바른 방법은 무엇입니까?감사합니다!
사용 안 함SQLERRM
또는SQLCODE
라인 번호를 저장하지 않고 예외를 기록하는 것은 잔인합니다.
항상 사용dbms_utility.format_error_stack||dbms_utility.format_error_backtrace
아니면 비슷한 것.
예를 들어 다음 블록에는 오류가 표시되지만 발생한 위치는 표시되지 않습니다.
declare
v_number number;
begin
v_number := 1/0;
exception when others then
dbms_output.put_line(sqlerrm);
end;
/
DBMS Output:
ORA-01476: divisor is equal to zero
이 블록에는 오류와 발생한 위치가 모두 표시됩니다.중요하지 않은 프로그램의 문제를 해결하는 데 중요한 정보입니다.
declare
v_number number;
begin
v_number := 1/0;
exception when others then
dbms_output.put_line(dbms_utility.format_error_stack||dbms_utility.format_error_backtrace);
end;
/
DBMS Output:
ORA-01476: divisor is equal to zero
ORA-06512: at line 4
(아래는 몇 가지 일반적인 예외 처리 권장 사항입니다.)
실제 코드의 경우 오류 정보를 단순히 출력하지 않습니다.실제로 가장 좋은 예외 처리 전략은 일반적으로 아무것도 하지 않고 Oracle의 기본 동작을 사용하여 모든 오류 메시지와 줄 번호를 표시하는 것입니다.
Oracle의 사용자 지정 예외 처리는 일반적으로 다음 세 가지 경우 중 하나에서만 유용합니다.
- 오류를 무시하는 다른 절차를 호출하는 등 특정 오류가 있는 작업을 수행합니다.
- 데이터베이스 전용 프로그램인 경우 프로그램 상단(제한된 수의 진입점)에서 예외를 포착하고 기록할 수 있습니다.응용 프로그램이 이미 모든 것을 인식하거나 내부 코드에 대해 예외 처리를 수행할 필요가 없습니다.예외는 스택 위로 전파되므로 마지막에 잡는 것이 가장 좋습니다.
- 로컬 변수로만 존재하는 특정 값을 기록해야 하는 경우 해당 값이 예외와 함께 전파되지 않으므로 즉시 기록해야 합니다.
모든 절차에서 오류를 맹목적으로 포착하고 기록하는 PL/SQL 코드가 많습니다.그것은 불필요하고 일반적으로 역효과를 낳습니다.
사용할 수 없습니다.SQLERRM
직접 - 중간 변수에 할당해야 합니다.Oracle 9i를 사용하면 문제를 해결할 수 있지만 항상 문서화된 동작입니다.샘플 코드는 여기를 참조하십시오.
PL/SQL 코드의 트랜잭션이 롤백되더라도 기록되도록 이 비트를 자동 트랜잭션으로 래핑하는 것도 고려할 수 있습니다.
가이우스가 당신에게 짧은 대답을 했습니다.그것을 자율적인 거래로 포장하는 것에 대한 그의 의견은 매우 중요합니다.당신은 당신의 거래가 철회된 날을 후회하게 될 것이고, 왜 그런지는 모릅니다.
여기에 오류가 발생한 위치에 대해 더 자세히 알 수 있도록 몇 가지 추가 세부 정보가 포함된 자율 트랜잭션을 사용하는 방법이 나와 있습니다.
예외 블록은 다음과 같이 됩니다.
exception
when exception_pkg.assertion_failure_exception then
rollback;
raise;
when others then
rollback;
v_code := SQLCODE;
v_errm := SUBSTR(SQLERRM, 1, 255);
exception_pkg.throw( exception_pkg.unhandled_except, v_code || ' - ' || v_errm || ' ($Header$)' );
aaa and, 여기 이것을 지원하는 데 필요한 모든 코드가 있습니다.가지고 놀아요, 유용해요 :-)
-- Create a table to hold the error messages
CREATE TABLE ERROR_MESSAGES
(
ERROR_MESSAGE_ID NUMBER(10) NOT NULL,
ERROR_DATE TIMESTAMP(6) DEFAULT SYSDATE NOT NULL,
ERROR_USER VARCHAR2(30 BYTE) DEFAULT USER NOT NULL,
MESSAGE_TYPE VARCHAR2(15 BYTE),
PACKAGE_NAME VARCHAR2(250 BYTE),
PROCEDURE_OR_LINE VARCHAR2(30 BYTE),
ERROR_CODE VARCHAR2(10 BYTE),
ERROR_MESSAGE1 VARCHAR2(4000 BYTE),
ERROR_MESSAGE2 VARCHAR2(4000 BYTE),
ERROR_MESSAGE3 VARCHAR2(4000 BYTE),
ERROR_MESSAGE4 VARCHAR2(4000 BYTE)
);
CREATE UNIQUE INDEX ERROR_MESSAGES_XPK ON ERROR_MESSAGES
(ERROR_MESSAGE_ID);
-- Create the sequence used for the ERROR_MESSAGES PK
CREATE SEQUENCE ERROR_MESSAGE_SEQ
START WITH 1;
-- The package
CREATE OR REPLACE PACKAGE EXCEPTION_PKG
as
/************************************************************************************
* $Header$
*
* Package: exception_pkg
*
* Purpose: Exception handling functionality
*
* Authors: M.McAllister (via AskTom - http://tinyurl.com/c43jt)
*
* Revision History:
*
* $Log[10]$
******************************************************************************************/
/*=====================================================================
* Constants
*=====================================================================*/
c_InfMsg constant error_messages.message_type%type := 'Informational';
c_WarnMsg constant error_messages.message_type%type := 'Warning';
c_ErrMsg constant error_messages.message_type%type := 'Fatal Error';
c_DbgMsg constant error_messages.message_type%type := 'Debug';
c_MaintMsg constant error_messages.message_type%type := 'Maintenance';
/*=====================================================================
* Exception Definitions
*=====================================================================*/
unhandled_except constant number := -20001;
unhandled_except_exception exception;
pragma exception_init(unhandled_except_exception, -20001);
bad_parameter constant number := -20002;
bad_parameter_exception exception;
pragma exception_init(bad_parameter_exception, -20002);
assertion_failure constant number := -20003;
assertion_failure_exception exception;
pragma exception_init(assertion_failure_exception, -20003);
/*=====================================================================
* Procedures
*=====================================================================*/
procedure write_exception_info( p_msg_type error_messages.message_type%type
, p_pkg_name error_messages.package_name%type
, p_func_name error_messages.procedure_or_line%type
, p_error_code error_messages.error_code%type
, p_msg1 error_messages.error_message2%type
, p_msg2 error_messages.error_message3%type
, p_msg3 error_messages.error_message4%type
);
procedure who_called_me( p_owner out varchar2,
p_name out varchar2,
p_lineno out number,
p_caller_t out varchar2,
p_my_depth in number default 3
);
procedure throw( p_exception in number
, p_extra_msg in varchar2 default NULL
);
end exception_pkg;
/
-- Package Body
CREATE OR REPLACE PACKAGE BODY EXCEPTION_PKG
as
/************************************************************************************
* $Header$
*
* Package: exception_pkg
*
* Purpose: Exception handling functionality
*
* Authors: M.McAllister (via AskTom - http://tinyurl.com/c43jt)
*
* Revision History:
*
* $Log[10]$
******************************************************************************************/
/*=====================================================================
* Types
*=====================================================================*/
type myArray is table of varchar2(255) index by binary_integer;
/*=====================================================================
* Globals
*=====================================================================*/
err_msgs myArray;
/*=====================================================================
* Procedures
*=====================================================================*/
procedure who_called_me( p_owner out varchar2,
p_name out varchar2,
p_lineno out number,
p_caller_t out varchar2,
p_my_depth in number default 3
)
as
call_stack varchar2(4096) default dbms_utility.format_call_stack;
n number;
found_stack BOOLEAN default FALSE;
line varchar2(255);
cnt number := 0;
begin
loop
n := instr( call_stack, chr(10) );
exit when ( cnt = p_my_depth or n is NULL or n = 0 );
line := substr( call_stack, 1, n-1 );
call_stack := substr( call_stack, n+1 );
if ( NOT found_stack ) then
if ( line like '%handle%number%name%' ) then
found_stack := TRUE;
end if;
else
cnt := cnt + 1;
-- cnt = 1 is ME
-- cnt = 2 is MY Caller
-- cnt = 3 is Their Caller
if ( cnt = p_my_depth ) then
p_lineno := to_number(substr( line, 13, 6 ));
line := substr( line, 21 );
if ( line like 'pr%' ) then
n := length( 'procedure ' );
elsif ( line like 'fun%' ) then
n := length( 'function ' );
elsif ( line like 'package body%' ) then
n := length( 'package body ' );
elsif ( line like 'pack%' ) then
n := length( 'package ' );
elsif ( line like 'anonymous%' ) then
n := length( 'anonymous block ' );
else
n := null;
end if;
if ( n is not null ) then
p_caller_t := ltrim(rtrim(upper(substr( line, 1, n-1 ))));
else
p_caller_t := 'TRIGGER';
end if;
line := substr( line, nvl(n,1) );
n := instr( line, '.' );
p_owner := ltrim(rtrim(substr( line, 1, n-1 )));
p_name := ltrim(rtrim(substr( line, n+1 )));
end if;
end if;
end loop;
end who_called_me;
/*=====================================================================
* PRIVATE function: get_session_info
* purpose: Returns a formatted string containing some information
* about the current session
*=====================================================================*/
function get_session_info return varchar2 is
l_sessinfo varchar2(2000);
begin
select
'[SID = ' || sid || '], ' ||
'[SERIAL# = ' || serial# ||'], ' ||
'[MACHINE = ' || replace(machine,chr(0),'') || '], ' ||
'[OSUSER = ' || osuser || '], ' ||
'[PROGRAM = ' || program || '], ' ||
'[LOGON_TIME = ' || to_char(logon_time,'mm/dd/yyyy hh:mi:ss') || ']' into l_sessinfo
from v$session
WHERE audsid = SYS_CONTEXT('userenv','sessionid');
return l_sessinfo;
end get_session_info;
/*=====================================================================
* procedure: write_exception_info
* purpose: Call the exception logging routine
*=====================================================================*/
procedure write_exception_info( p_msg_type error_messages.message_type%type
, p_pkg_name error_messages.package_name%type
, p_func_name error_messages.procedure_or_line%type
, p_error_code error_messages.error_code%type
, p_msg1 error_messages.error_message2%type
, p_msg2 error_messages.error_message3%type
, p_msg3 error_messages.error_message4%type
) is
-- This procedure is autonomous from the calling procedure.
-- i.e The calling procedure does not have to be complete
-- for this procedure to commit its changes.
pragma autonomous_transaction;
l_sessinfo varchar2(2000);
begin
l_sessinfo := get_session_info;
insert into error_messages
( error_message_id
, error_date
, error_user
, message_type
, package_name
, procedure_or_line
, error_code
, error_message1
, error_message2
, error_message3
, error_message4
)
values
( error_message_seq.nextval
, sysdate
, USER
, p_msg_type
, p_pkg_name
, p_func_name
, p_error_code
, l_sessinfo
, p_msg1
, p_msg2
, p_msg3
);
commit;
exception
when others then
-- We don't want an error logging a message to
-- cause the application to crash
return;
end write_exception_info;
procedure throw( p_exception in number
, p_extra_msg in varchar2 default NULL
) is
l_owner varchar2(30);
l_name varchar2(30);
l_type varchar2(30);
l_line number;
l_exception number;
begin
who_called_me( l_owner, l_name, l_line, l_type );
write_exception_info( c_ErrMsg
, l_owner || '.' || l_name
, 'Line ' || l_line
, p_exception
, p_extra_msg
, NULL
, err_msgs(p_exception)
);
raise_application_error( p_exception
, 'Exception at ' || l_type || ' ' ||
l_owner || '.' || l_name || '(' || l_line || '). ' ||
err_msgs(p_exception ) || '. ' || p_extra_msg
, TRUE );
exception
-- we will get this when we have an invalid exception code, one
-- that was not set in the err_msgs array below. The plsql table
-- access will raise the NO-DATA-FOUND exception. We'll catch it,
-- verify the exception code is in the valid range for raise_application_error
-- (if not, set to -20000) and then raise the exception with the message
-- "unknown error"
when NO_DATA_FOUND then
if ( p_exception between -20000 and -20999 ) then
l_exception := p_exception;
else
l_exception := -20000;
end if;
write_exception_info( c_ErrMsg
, l_owner || '.' || l_name
, 'Line ' || l_line
, p_exception
, p_extra_msg
, NULL
, '**UNKNOWN ERROR**'
);
raise_application_error( l_exception
, 'Exception at ' || l_type || ' ' ||
l_owner || '.' || l_name || '(' || l_line || '). ' ||
'**UNKNOWN ERROR**' || '. ' || p_extra_msg
, TRUE );
end throw;
begin
-- This code is run once per session when this package is first touched
err_msgs( unhandled_except ) := 'Unhandled exception';
err_msgs( bad_parameter ) := 'Invalid parameter passed into function or procedure';
err_msgs( assertion_failure ) := 'Program execution stopped due to assertion failure';
end exception_pkg;
/
언급URL : https://stackoverflow.com/questions/9184865/how-to-log-all-exceptions-in-oracle-package
'programing' 카테고리의 다른 글
근처의 구문이 잘못됨 (0) | 2023.08.20 |
---|---|
도커: 프로젝트의 여러 도커 파일 (0) | 2023.08.20 |
시간 초과 jQuery 효과 (0) | 2023.08.20 |
Powershell 모듈에서 "헬퍼" 기능을 숨기는 방법 (0) | 2023.08.20 |
Grafana에 대해 SQL 쿼리로 선택한 시간 간격을 기반으로 동적으로 가동 시간 계산 (0) | 2023.08.20 |