我在 Oracle 中调试触发器时遇到了困难。目前我正在使用 Oracle 的 Sql Developer 工具。
为了测试触发器,我在测试窗口中编写了插入或删除,但我看不到触发器内部发生了什么。我想逐步检查触发器,看看触发器触发时发生了什么。有没有办法使用 select 语句在触发器中显示变量值?
我在 Oracle 中调试触发器时遇到了困难。目前我正在使用 Oracle 的 Sql Developer 工具。
为了测试触发器,我在测试窗口中编写了插入或删除,但我看不到触发器内部发生了什么。我想逐步检查触发器,看看触发器触发时发生了什么。有没有办法使用 select 语句在触发器中显示变量值?
Firstly, don't "start from here", or more specifically, don't use triggers. Triggers are going to force switching to row-level processing if the triggers are going to fire for each row. It's better to put the logic in a stored procedure which you call. You've then got a start (where you validate inputs) and an end and a logic path all the way through. Stored procedures are a lot easier to debug as you follow one path.
Second, never test for an error you don't know how to handle. If you don't catch it, it bubbles up to the client who gets an error report saying what went wrong (error message) and where (i.e. the error/call stack). If you try to catch it, you have to know what to do with it (and if you don't know the tendency is to ignore it - which is BAD).
Finally, you can't readily see each 'layer' of a select. The explain plan will generally tell you how its going about things. v$session_longops MAY indicate what it is currently doing. The current wait event MAY give clues as to what table/block/row it is currently working on.
如果您必须调试触发器,一个粗略的简单方法是使用DBMS_OUTPUT。
例如
SQL> CREATE OR REPLACE TRIGGER mytrigger
BEFORE UPDATE ON mytable
FOR EACH ROW
...
BEGIN
DBMS_OUTPUT.put_line('mytrigger STARTING');
... do some logic ...
DBMS_OUTPUT.put_line('old=' || :OLD.mycolumn);
DBMS_OUTPUT.put_line('new=' || :NEW.mycolumn);
DBMS_OUTPUT.put_line('mytrigger FINISHED');
END;
/
SQL> SET SERVEROUT ON
SQL> UPDATE mytable SET mycolumn = mycolumn + 1;
2 rows updated.
mytrigger STARTING
old=10
new=11
mytrigger FINISHED
mytrigger STARTING
old=20
new=21
mytrigger FINISHED
应用程序 我使用来自 www.quest.com/toad/toad-for-oracle.aspx 的名为 TOAD 的 Quest 程序。
如上所述,DBMS_OUTPUT 非常方便。在您的编辑器中,确保启用“输出”窗口。
PL/SQL 在代码“块”上工作,您可以使用 EXCEPTION 关键字捕获它。
(请原谅我的格式,不知道如何格式化网络)
DECLARE
C_DATE_FORMAT VARCHAR2(20) := 'DD-Mon-YYYY';
C_TIME_FORMAT VARCHAR2(20) := 'HH24:MI:SS';
C_NOT_IMPLEMENTED_CODE CONSTANT NUMBER(5) := -20200;
C_NOT_IMPLEMENTED_MESSAGE CONSTANT VARCHAR2(255) := 'Not implemented';
not_implemented EXCEPTION; -- user defined exception
BEGIN
--RAISE not_implemented; -- raise user defined exception
RAISE_APPLICATION_ERROR(C_NOT_IMPLEMENTED_CODE, C_NOT_IMPLEMENTED_MESSAGE); -- user defined exception
EXCEPTION -- exception block
WHEN not_implemented THEN -- catch not_implemented exception
DBMS_OUTPUT.PUT_LINE('Error: Not implemented');
WHEN OTHERS THEN -- catch all other exceptions
DBMS_OUTPUT.PUT_LINE('Error occured.');
DBMS_OUTPUT.PUT_LINE('Date: ' || TO_CHAR(SYSDATE, C_DATE_FORMAT));
DBMS_OUTPUT.PUT_LINE('Time: ' || TO_CHAR(SYSDATE, C_TIME_FORMAT));
DBMS_OUTPUT.PUT_LINE('Error code: ' || SQLCODE);
DBMS_OUTPUT.PUT_LINE('Error message: ' || SQLERRM); --deal with error
RAISE; -- raise to calling object
END;