PL/SQL & T-SQL (Oracle and SQL Server) Module 11 – Subprograms, packages and robust error logging
Error logging, backtraces and autonomous logs
Record where a PL/SQL error happened with SQLERRM, backtraces and the call stack, and see how autonomous logs outlive a rollback.
What you will learn
- Record where an error happened with FORMAT_ERROR_BACKTRACE and UTL_CALL_STACK
- Write a logging package whose entries survive a rollback
- Avoid autonomous-transaction pitfalls, missing commits and self-deadlocks
- Build log records that keep personal data out
Before you start
What you’ll learn · Before you start
What you will learn
- Record where an error happened with FORMAT_ERROR_BACKTRACE and UTL_CALL_STACK
- Write a logging package whose entries survive a rollback
- Avoid autonomous-transaction pitfalls, missing commits and self-deadlocks
- Build log records that keep personal data out
Before you start
On this page
Account 3 holds 760.25, and a month-end fee of 1000.00 stops the run with ORA-02290, three procedures deep. The message names the broken rule but not the place, and a log row written before the rollback disappears with the rollback.
Error logging answers both problems. SQLERRM gives the message, DBMS_UTILITY.FORMAT_ERROR_BACKTRACE gives the chain of line numbers from the failing statement up to the handler, and UTL_CALL_STACK numbers the same frames. A logger that runs as an autonomous transaction: A transaction of its own that a routine marked PRAGMA AUTONOMOUS_TRANSACTION runs while the main transaction waits; its COMMIT keeps its changes whatever the caller does afterwards. commits its own row, so the row stays when the caller rolls back. You will read a backtrace, name its origin and say what a safe log row holds.
The message says what failed, the backtrace says where
In the fee run of backtrace_demo.sql, close_month calls settle_account, which calls charge_fee, and charge_fee runs an UPDATE that would take account 3 below zero. The check constraint refuses it with ORA-02290.
SQLERRM returns the message of that error, ORA-02290: check constraint (LAB.ACCOUNTS_BALANCE_CK) violated, and says nothing about where it happened. It returns at most 512 bytes, so Oracle recommends DBMS_UTILITY.FORMAT_ERROR_STACK, which returns the whole error stack: The messages of an error and of the errors it caused. DBMS_UTILITY.FORMAT_ERROR_STACK returns them as text of up to 2000 bytes, where SQLERRM returns at most 512 bytes. up to 2000 bytes. The place comes from FORMAT_ERROR_BACKTRACE: The DBMS_UTILITY function that, inside a handler, returns one ORA-06512 line for each frame, from the statement that failed to the unit holding the handler; it returns NULL when no error is being handled.: one ORA-06512 line for each frame, from the statement that failed up to the unit that holds the handler. Backtraces are for reading inside a handler, because the function returns NULL when no error is being handled. Step the error up through the three units:
The drawing shows the whole scene; its 4 steps are listed below.
Every step as text
- The UPDATE breaks a rule. charge_fee runs its UPDATE, on line 4, for account 3, which holds 760.25. A fee of 1000.00 would take the balance below 0 and break accounts_balance_ck, so Oracle raises ORA-02290. charge_fee has no handler.
- Up to settle_account. Without a handler the error leaves charge_fee and arrives in settle_account at the statement that called it, on line 6. That line becomes a second frame of the backtrace.
- Up again to close_month. settle_account has no handler either, so the error arrives in close_month at its call on line 7. close_month has a handler, so the error stops climbing here, and line 7 is the third frame, the one nearest the handler.
- The handler reads the chain. FORMAT_ERROR_BACKTRACE returns one ORA-06512 line for each frame, origin first - CHARGE_FEE line 4, SETTLE_ACCOUNT line 6, CLOSE_MONTH line 7. UTL_CALL_STACK numbers the frames in the same order, index 1 for CHARGE_FEE and index 3, the depth, for CLOSE_MONTH. SQLERRM holds only the message.
The script runs both fee calls and prints what the handler in close_month sees. The Python model beside it finds each line number by searching the text of the three procedures, so the numbers cannot drift from the code:
-- Engine: Oracle AI Database 26ai Free, Release 23.26.3.0.0; user LAB in FREEPDB1. Client: SQL*Plus or SQLcl.
-- Three nested procedures: close_month calls settle_account, which calls charge_fee, and charge_fee breaks
-- accounts_balance_ck. The handler in close_month prints SQLERRM, the backtrace and the numbered frames of
-- UTL_CALL_STACK. Run schema_oracle.sql of practice-schema-and-dialect-basics first; examples/model/backtrace_model.py
-- derives the same line numbers from this source. The script rolls back its change and drops its procedures.
SET SERVEROUTPUT ON
SET LINESIZE 200
CREATE OR REPLACE PROCEDURE charge_fee (p_account_id IN NUMBER, p_fee IN NUMBER)
AUTHID DEFINER IS
BEGIN
UPDATE accounts SET balance = balance - p_fee WHERE account_id = p_account_id;
END charge_fee;
/
CREATE OR REPLACE PROCEDURE settle_account (p_account_id IN NUMBER, p_fee IN NUMBER)
AUTHID DEFINER IS
v_label CONSTANT VARCHAR2(20) := 'month-end fee';
BEGIN
DBMS_OUTPUT.PUT_LINE('settling ' || v_label);
charge_fee(p_account_id, p_fee);
END settle_account;
/
CREATE OR REPLACE PROCEDURE close_month (p_account_id IN NUMBER, p_fee IN NUMBER)
AUTHID DEFINER IS
v_run CONSTANT VARCHAR2(20) := 'month-end fee run';
BEGIN
DBMS_OUTPUT.PUT_LINE('closing account ' || p_account_id || ' for ' || v_run);
-- the fee run starts here
settle_account(p_account_id, p_fee);
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('SQLERRM: ' || SQLERRM);
DBMS_OUTPUT.PUT_LINE(DBMS_UTILITY.FORMAT_ERROR_BACKTRACE);
FOR i IN 1 .. UTL_CALL_STACK.BACKTRACE_DEPTH LOOP
DBMS_OUTPUT.PUT_LINE(i || ' ' || UTL_CALL_STACK.BACKTRACE_UNIT(i) || ' line ' || UTL_CALL_STACK.BACKTRACE_LINE(i));
END LOOP;
END close_month;
/
-- Expected: the three procedures are created, and each unit's line 1 is the line that holds PROCEDURE (the CREATE OR
-- REPLACE words count as part of it). The statement that fails is on line 4 of charge_fee, the call to charge_fee on
-- line 6 of settle_account and the call to settle_account on line 7 of close_month.
BEGIN
close_month(3, 10.00); -- 760.25 - 10.00 = 750.25: no error, so the handler never runs
close_month(3, 1000.00); -- 760.25 - 1000.00 breaks accounts_balance_ck (ORA-02290)
END;
/
-- Expected:
-- closing account 3 for month-end fee run
-- settling month-end fee
-- closing account 3 for month-end fee run
-- settling month-end fee
-- SQLERRM: ORA-02290: check constraint (LAB.ACCOUNTS_BALANCE_CK) violated
-- ORA-06512: at "LAB.CHARGE_FEE", line 4
-- ORA-06512: at "LAB.SETTLE_ACCOUNT", line 6
-- ORA-06512: at "LAB.CLOSE_MONTH", line 7
-- 1 LAB.CHARGE_FEE line 4
-- 2 LAB.SETTLE_ACCOUNT line 6
-- 3 LAB.CLOSE_MONTH line 7
-- The backtrace text and UTL_CALL_STACK both start at the origin: index 1 is the failing UPDATE, and index
-- BACKTRACE_DEPTH, 3 here, the call in the unit that examines the backtrace. BACKTRACE_UNIT names each unit with its
-- owner.
ROLLBACK;
DROP PROCEDURE close_month;
DROP PROCEDURE settle_account;
DROP PROCEDURE charge_fee; """backtrace_demo.sql in the lab: SQL*Plus runs it as LAB on a freshly loaded practice schema."""
from oracle_session import Lab
with Lab() as lab:
lab.sqlplus("backtrace/backtrace_demo.sql") Output
$ sqlplus -s lab@//localhost/FREEPDB1 @backtrace/backtrace_demo.sql Procedure created. Procedure created. Procedure created. closing account 3 for month-end fee run settling month-end fee closing account 3 for month-end fee run settling month-end fee SQLERRM: ORA-02290: check constraint (LAB.ACCOUNTS_BALANCE_CK) violated ORA-06512: at "LAB.CHARGE_FEE", line 4 ORA-06512: at "LAB.SETTLE_ACCOUNT", line 6 ORA-06512: at "LAB.CLOSE_MONTH", line 7 1 LAB.CHARGE_FEE line 4 2 LAB.SETTLE_ACCOUNT line 6 3 LAB.CLOSE_MONTH line 7 PL/SQL procedure successfully completed. Rollback complete. Procedure dropped. Procedure dropped. Procedure dropped.
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 backtrace_demo_session.py
"""Where an error happened: the backtrace of three nested procedures, modelled.
The model holds the text of the three procedures of backtrace_demo.sql. It finds
the line of each statement by searching the text, as Oracle counts it (line 1 is
the line that holds PROCEDURE), and prints what the documented functions return
when charge_fee breaks accounts_balance_ck:
1. DBMS_UTILITY.FORMAT_ERROR_BACKTRACE lists one ORA-06512 line per frame, from
the statement that failed to the line of the unit that holds the handler.
2. UTL_CALL_STACK numbers the same frames in the same order: BACKTRACE_LINE(1)
is the origin, the line on which the error was raised, and
BACKTRACE_LINE(BACKTRACE_DEPTH) is the call in the unit that examines the
backtrace. BACKTRACE_UNIT names each unit with its owner. The depth is 0 with
no error.
Edit HANDLERS to move the handler to another unit, or insert a line into a
procedure and watch the numbers follow.
"""
UPDATE = "UPDATE accounts SET balance = balance - p_fee "
SOURCE = {
"CHARGE_FEE": [
"PROCEDURE charge_fee (p_account_id IN NUMBER, p_fee IN NUMBER)",
" AUTHID DEFINER IS",
"BEGIN",
" " + UPDATE + "WHERE account_id = p_account_id;",
"END charge_fee;",
],
"SETTLE_ACCOUNT": [
"PROCEDURE settle_account (p_account_id IN NUMBER, p_fee IN NUMBER)",
" AUTHID DEFINER IS",
" v_label CONSTANT VARCHAR2(20) := 'month-end fee';",
"BEGIN",
" DBMS_OUTPUT.PUT_LINE('settling ' || v_label);",
" charge_fee(p_account_id, p_fee);",
"END settle_account;",
],
"CLOSE_MONTH": [
"PROCEDURE close_month (p_account_id IN NUMBER, p_fee IN NUMBER)",
" AUTHID DEFINER IS",
" v_run CONSTANT VARCHAR2(20) := 'month-end fee run';",
"BEGIN",
" DBMS_OUTPUT.PUT_LINE('closing account ' || p_account_id);",
" -- the fee run starts here",
" settle_account(p_account_id, p_fee);",
"EXCEPTION",
" WHEN OTHERS THEN",
" DBMS_OUTPUT.PUT_LINE(DBMS_UTILITY.FORMAT_ERROR_BACKTRACE);",
"END close_month;",
],
}
CALL_CHAIN = ["CLOSE_MONTH", "SETTLE_ACCOUNT", "CHARGE_FEE"] # outermost first
ERROR = "ORA-02290: check constraint (LAB.ACCOUNTS_BALANCE_CK) violated"
HANDLERS = ["CLOSE_MONTH", "SETTLE_ACCOUNT"] # one case per handler
def line_of(unit, start):
"""Number of the first line of the unit that starts with the text."""
for number, text in enumerate(SOURCE[unit], start=1):
if text.strip().startswith(start):
return number
raise ValueError(f"{start!r} not found in {unit}")
def statement_line(unit):
"""Line of the statement that raises, or that calls the next unit."""
if unit == CALL_CHAIN[-1]:
return line_of(unit, "UPDATE accounts"), "UPDATE"
callee = CALL_CHAIN[CALL_CHAIN.index(unit) + 1].lower()
return line_of(unit, callee + "("), "call to " + callee
def frames(handler):
"""Backtrace frames, origin first, ending with the handler's own unit."""
inner = CALL_CHAIN[CALL_CHAIN.index(handler):]
return [(unit, statement_line(unit)[0]) for unit in reversed(inner)]
print("Lines found by searching the source of each unit")
for unit in CALL_CHAIN:
line, what = statement_line(unit)
print(f" {unit:<15}{what} at line {line}")
for handler in HANDLERS:
stack = frames(handler)
print(f"\nHandler in {handler}")
print(f" SQLERRM: {ERROR}")
print(" FORMAT_ERROR_BACKTRACE:")
for unit, line in stack:
print(f' ORA-06512: at "LAB.{unit}", line {line}')
print(f" UTL_CALL_STACK.BACKTRACE_DEPTH = {len(stack)}")
for index, (unit, line) in enumerate(stack, start=1): # index 1 is the origin
mark = ""
if index == 1:
mark += " <- origin"
if index == len(stack):
mark += " <- the handler's unit"
print(f" {index} LAB.{unit} line {line}{mark}")
print("\nNo error being handled")
print(" FORMAT_ERROR_BACKTRACE = NULL")
print(" UTL_CALL_STACK.BACKTRACE_DEPTH = 0") Output
Lines found by searching the source of each unit
CLOSE_MONTH call to settle_account at line 7
SETTLE_ACCOUNT call to charge_fee at line 6
CHARGE_FEE UPDATE at line 4
Handler in CLOSE_MONTH
SQLERRM: ORA-02290: check constraint (LAB.ACCOUNTS_BALANCE_CK) violated
FORMAT_ERROR_BACKTRACE:
ORA-06512: at "LAB.CHARGE_FEE", line 4
ORA-06512: at "LAB.SETTLE_ACCOUNT", line 6
ORA-06512: at "LAB.CLOSE_MONTH", line 7
UTL_CALL_STACK.BACKTRACE_DEPTH = 3
1 LAB.CHARGE_FEE line 4 <- origin
2 LAB.SETTLE_ACCOUNT line 6
3 LAB.CLOSE_MONTH line 7 <- the handler's unit
Handler in SETTLE_ACCOUNT
SQLERRM: ORA-02290: check constraint (LAB.ACCOUNTS_BALANCE_CK) violated
FORMAT_ERROR_BACKTRACE:
ORA-06512: at "LAB.CHARGE_FEE", line 4
ORA-06512: at "LAB.SETTLE_ACCOUNT", line 6
UTL_CALL_STACK.BACKTRACE_DEPTH = 2
1 LAB.CHARGE_FEE line 4 <- origin
2 LAB.SETTLE_ACCOUNT line 6 <- the handler's unit
No error being handled
FORMAT_ERROR_BACKTRACE = NULL
UTL_CALL_STACK.BACKTRACE_DEPTH = 0
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 backtrace_model.py
Runs on this device, in your browser. The first run downloads Python (about 13.5 MB), which is kept for the next runs.
Your run, in this browser
Move the origin by one line
Press Edit and add the string " -- fee check", after "BEGIN", in the CHARGE_FEE list, then run it again: the
origin becomes line 5 of CHARGE_FEE, and the other two frames stay at lines 6 and 7.
Checkpoint
Check: The message and the backtrace
Numbered frames start at the origin
UTL_CALL_STACK: The PL/SQL package that returns the frames of a backtrace or of the call stack as numbers and names, such as BACKTRACE_DEPTH, BACKTRACE_UNIT and BACKTRACE_LINE, instead of one formatted text. gives backtraces as numbers instead of text. UTL_CALL_STACK.BACKTRACE_DEPTH counts the frames, and BACKTRACE_UNIT(i) and BACKTRACE_LINE(i) return the unit and the line of frame i. The numbers start at the origin: index 1 is the unit where the error was raised, and the highest index, backtrace depth: The number of frames in a backtrace, returned by UTL_CALL_STACK.BACKTRACE_DEPTH. Index 1 is the origin of the error, the highest index is the unit that examines the backtrace, and the depth is 0 when no error is being handled., is the unit that examines the backtrace. So BACKTRACE_LINE(1) is the line that raised the error, and BACKTRACE_LINE(BACKTRACE_DEPTH) the call in the handler’s unit. The handler in close_month prints, and the model with it:
| Index | Unit | Line | What the frame is |
|---|---|---|---|
| 1 | LAB.CHARGE_FEE | 4 | the origin, the failing UPDATE |
| 2 | LAB.SETTLE_ACCOUNT | 6 | the call to charge_fee |
| 3 | LAB.CLOSE_MONTH | 7 | the call in the unit with the handler |
That is the order of the FORMAT_ERROR_BACKTRACE text, and BACKTRACE_UNIT names each unit with its owner. With the handler in settle_account the same error has two frames, CHARGE_FEE at index 1 and SETTLE_ACCOUNT at index 2, because a backtrace ends where it is examined. With no error being handled the depth is 0. The call stack also counts from the innermost frame: its dynamic depth 1 is the subprogram running now.
Checkpoint
Check: Numbered frames, origin first
A log row written in the failing transaction rolls back with it
Suppose the handler inserts a log row into the table app_log and the caller then rolls back. The row was part of the caller’s transaction, so the rollback removes it together with the fee, and the failure leaves no trace. Good error logging writes the row where a rollback cannot reach it. The table sets the two places side by side:
| Where the row is written | After the caller’s ROLLBACK |
|---|---|
| In the caller’s transaction | gone, with everything else the caller changed |
| In an autonomous transaction | kept, because it committed on its own |
Autonomous logs take the second route. PRAGMA AUTONOMOUS_TRANSACTION gives the logger a transaction of its own, so its COMMIT keeps its row whatever the caller does later. Two pitfalls come with autonomous logs. A routine that returns without COMMIT or ROLLBACK raises ORA-06519, and one that updates a row its caller has locked deadlocks with the caller and raises ORA-00060. Safe log design decides what a row may hold: the error stack, the backtrace, the module and a correlation id, and never full account numbers, phone numbers or names. SQL Server has the same problem, treated under doomed transactions, and the logger is a package, as in the lesson on packages.
Checkpoint
Check: A log row that a rollback removes
A logger whose rows survive a caller rollback Pro: opens with a Pro, Premium or Ultimate pass
A logger that commits in a transaction of its own keeps its row when the caller rolls back. It pays for that with a blind spot and two traps, and all three are reproduced below on account 3.
In this part:
- Writing a logger that commits its own row
- What the logger can see while the fee is pending
- Two pitfalls reproduced: ORA-06519 and ORA-00060
1 diagram · 5 runnable examples (Python, SQL) · about 8 minutes
Opening this part with your pass…
This part opens with any MySmartCoPilot pass.
- Pro pass · 1 week₹79$2.99
- 30 days₹179$5.99
- 1 year₹1,699$45
One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.
Passes can’t be bought right now, so this part can’t be opened at the moment. The free part above stands on its own. If you have a pass, enter your licence key.
It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).
Backtraces that pinpoint the failing line, safely Pro: opens with a Pro, Premium or Ultimate pass
A log row is only as useful as the place it names and only as safe as the data it holds. The position of the handler, the fields of the row and the width of its columns decide both.
In this part:
- Where the handler sits decides how many frames you see
- Choosing what a log row keeps and what it leaves out
- Storing the whole error stack in a column that fits it
3 runnable examples (Python, SQL) · about 12 minutes
Opening this part with your pass…
This part opens with any MySmartCoPilot pass.
- Pro pass · 1 week₹79$2.99
- 30 days₹179$5.99
- 1 year₹1,699$45
One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.
Passes can’t be bought right now, so this part can’t be opened at the moment. The free part above stands on its own. If you have a pass, enter your licence key.
It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).
Practise: place the error, then place the log row
Each question gives a failing call chain or a log design. Name the frame or the transaction first, then choose:
Practice that adapts to you
Practise this lesson
7 questions about 9 ideas of this lesson. Each answer is explained at once, and what you get right is kept in this browser.
Interview questions
Warm-up (fresher): how do SQLERRM and FORMAT_ERROR_BACKTRACE differ?
SQLERRM returns the text of the error being handled, up to 512 bytes. DBMS_UTILITY.FORMAT_ERROR_BACKTRACE returns where it happened: one ORA-06512 line for each frame, with the unit and the line number, from the failing statement to the handler. The first says which rule broke and the second which line broke it, so a log row needs both. Outside a handler the backtrace function returns NULL.
Three longer questions cover an empty log table, a hanging logger and customer details in log messages:
-
Mid to senior
A nightly settlement job catches each failure in an OTHERS handler, inserts a row into an error table and raises the error again. The scheduler rolls the batch back on the error, and next morning the table is empty although the job log shows 40 failed accounts. Explain the empty table and change the logging.
-
Senior to staff
A procedure marks an invoice paid and then calls a logging procedure declared with PRAGMA AUTONOMOUS_TRANSACTION. The logger also updates the note column of the same invoice row. With one user on the system, calls fail with ORA-00060. Explain the error and redesign the logger.
-
Mid to staff
Support asks the developers of a payments module to add the customer's name, phone number and full account number to every error row, so that tickets move faster. Decide what each row holds instead, and how support still finds the customer.
Flashcards · 7 cards
Recall it, then check
Say the answer to yourself before you look: recalling it is what makes it stick.
-
What does SQLERRM tell you, and what does it leave out?
The error's message, such as ORA-02290 naming the broken check constraint, and nothing about where it happened. It returns at most 512 bytes, so Oracle recommends DBMS_UTILITY.FORMAT_ERROR_STACK, which returns the whole error stack up to 2000 bytes.
-
What does DBMS_UTILITY.FORMAT_ERROR_BACKTRACE return?
One ORA-06512 line for each frame, from the statement that failed up to the unit holding the handler. It is for reading inside a handler: the function returns NULL when no error is being handled.
-
Which end do UTL_CALL_STACK's backtrace indexes start from?
Index 1 is the origin, the frame of the statement that raised the error, and the highest index, BACKTRACE_DEPTH, is the unit that examines the backtrace, the handler's own unit. So BACKTRACE_LINE(1) is the failing line, in the same order as the FORMAT_ERROR_BACKTRACE text, which starts at the origin too.
-
How many frames does a backtrace have, and what is the depth outside a handler?
It ends where it is examined, so the same error seen by a handler one level down has one frame fewer. With no error being handled the depth is 0. The call stack counts the same way: dynamic depth 1 is the subprogram running now.
-
What happens to a log row the handler wrote in the caller's transaction?
The caller's ROLLBACK removes it together with everything else the caller changed, so the failure leaves no trace. A row written in a transaction of its own is kept, because it committed on its own.
-
What does PRAGMA AUTONOMOUS_TRANSACTION give a logger?
A transaction of its own, so its COMMIT keeps its row whatever the caller does later.
-
Which two errors wait for a careless autonomous routine?
ORA-06519 when it returns without a COMMIT or ROLLBACK, and ORA-00060 when it updates a row its caller has locked, because it deadlocks with its own caller.
Key takeaways
- The message of an error says which rule broke, and the backtrace says where, as one ORA-06512 line for each frame from the failing statement to the handler.
UTL_CALL_STACKnumbers the same frames in the same order: index 1 is the origin, the unit that examines the backtrace is at indexBACKTRACE_DEPTH, and the depth is 0 outside a handler.- A log row written in the caller’s transaction is rolled back with it, so a logger needs a transaction of its own.
Terms in this lesson
- autonomous transaction
- A transaction of its own that a routine marked PRAGMA AUTONOMOUS_TRANSACTION runs while the main transaction waits; its COMMIT keeps its changes whatever the caller does afterwards.
- backtrace depth
- The number of frames in a backtrace, returned by UTL_CALL_STACK.BACKTRACE_DEPTH. Index 1 is the origin of the error, the highest index is the unit that examines the backtrace, and the depth is 0 when no error is being handled.
- error stack
- The messages of an error and of the errors it caused. DBMS_UTILITY.FORMAT_ERROR_STACK returns them as text of up to 2000 bytes, where SQLERRM returns at most 512 bytes.
- FORMAT_ERROR_BACKTRACE
- The DBMS_UTILITY function that, inside a handler, returns one ORA-06512 line for each frame, from the statement that failed to the unit holding the handler; it returns NULL when no error is being handled.
- UTL_CALL_STACK
- The PL/SQL package that returns the frames of a backtrace or of the call stack as numbers and names, such as BACKTRACE_DEPTH, BACKTRACE_UNIT and BACKTRACE_LINE, instead of one formatted text.
References
- PL/SQL Packages and Types Reference 26ai: DBMS_UTILITY (Oracle)
- PL/SQL Packages and Types Reference 26ai: UTL_CALL_STACK (Oracle)
- PL/SQL Language Reference 26ai: Retrieving Error Code and Error Message (Oracle)
- PL/SQL Language Reference 26ai: Autonomous Transactions (Oracle)
- PL/SQL Language Reference 26ai: AUTONOMOUS_TRANSACTION Pragma (Oracle)
- Database Error Messages: ORA-06519 (Oracle)
- Database Error Messages: ORA-00060 (Oracle)
- Database Error Messages: ORA-06512 (Oracle)
- Database Error Messages: ORA-02290 (Oracle)
- Database Error Messages: ORA-12899 (Oracle)
- Database Error Messages: ORA-00054 (Oracle)
- Database Error Messages: ORA-40097 (Oracle)
- Logging Cheat Sheet (OWASP)
Report a problem with this lesson
Kept only in this browser. Your Learn progress