PL/SQL Automatic Constraint Handler(Code)
For those interested...
I created the following database code that automatically does the constraint check/return error message for you.
You could even take this a step further and create your own message repository...
This guy even grabs/checks for foreign key violations:
First part of code builds/returns dictionary data constraints for table that you specify.
It then loads this data into object type.
This object type will be referenced later in the database trigger that you create for table where you want to validate constraints
return DbCons_documents_Array
as
dbdata DbCons_documents_Array := DbCons_documents_Array();
i NUMBER := 1;
begin
FOR cns_rec IN(select child.child_cons_name clchild_cons_name,
child.parent_cons_name clparent_cons_name,
child.child_columns clchild_columns,
parent.parent_cons_name pparent_cons_name,
parent.parent_tname pparent_tname,
child.child_tname clchild_tname,
CONCAT(CONCAT('"',replace(replace(parent.parent_columns,'"',''),'''','')),'"') pparent_columns,
child.parent_cons_type pparent_cons_type
--CONCAT(CONCAT('''',web_form_array(find_web_frm_val).db_col_value),'''');
FROM (
select a.table_name child_tname,
a.constraint_name child_cons_name,
NVL(b.r_constraint_name,a.constraint_name) parent_cons_name,
b.constraint_type parent_cons_type,
max(decode(position, 1, '"'||column_name||'"',NULL)) ||
max(decode(position, 2,', '||'"'||column_name||'"',NULL)) ||
max(decode(position, 3,', '||'"'||column_name||'"',NULL)) ||
max(decode(position, 4,', '||'"'||column_name||'"',NULL)) ||
max(decode(position, 5,', '||'"'||column_name||'"',NULL)) ||
max(decode(position, 6,', '||'"'||column_name||'"',NULL)) ||
max(decode(position, 7,', '||'"'||column_name||'"',NULL)) ||
max(decode(position, 8,', '||'"'||column_name||'"',NULL)) ||
max(decode(position, 9,', '||'"'||column_name||'"',NULL)) ||
max(decode(position,10,', '||'"'||column_name||'"',NULL)) ||
max(decode(position,11,', '||'"'||column_name||'"',NULL)) ||
max(decode(position,12,', '||'"'||column_name||'"',NULL)) ||
max(decode(position,13,', '||'"'||column_name||'"',NULL)) ||
max(decode(position,14,', '||'"'||column_name||'"',NULL)) ||
max(decode(position,15,', '||'"'||column_name||'"',NULL)) ||
max(decode(position,16,', '||'"'||column_name||'"',NULL))
child_columns
from user_cons_columns a, user_constraints b
where a.constraint_name = b.constraint_name
and b.constraint_type IN ( 'U', 'R' )
--and nvl(B.r_constraint_name,B.constraint_name) = A.constraint_name
-- and nvl(a.r_owner,a.owner) = b.owner
group by a.table_name, a.constraint_name, b.r_constraint_name,b.constraint_type ) child,
( select a.constraint_name parent_cons_name,
a.table_name parent_tname,
max(decode(position, 1, '"'||column_name||'"',NULL)) ||
max(decode(position, 2,', '||'"'||column_name||'"',NULL)) ||
max(decode(position, 3,', '||'"'||column_name||'"',NULL)) ||
max(decode(position, 4,', '||'"'||column_name||'"',NULL)) ||
max(decode(position, 5,', '||'"'||column_name||'"',NULL)) ||
max(decode(position, 6,', '||'"'||column_name||'"',NULL)) ||
max(decode(position, 7,', '||'"'||column_name||'"',NULL)) ||
max(decode(position, 8,', '||'"'||column_name||'"',NULL)) ||
max(decode(position, 9,', '||'"'||column_name||'"',NULL)) ||
max(decode(position,10,', '||'"'||column_name||'"',NULL)) ||
max(decode(position,11,', '||'"'||column_name||'"',NULL)) ||
max(decode(position,12,', '||'"'||column_name||'"',NULL)) ||
max(decode(position,13,', '||'"'||column_name||'"',NULL)) ||
max(decode(position,14,', '||'"'||column_name||'"',NULL)) ||
max(decode(position,15,', '||'"'||column_name||'"',NULL)) ||
max(decode(position,16,', '||'"'||column_name||'"',NULL))
parent_columns
from user_cons_columns a, user_constraints b
where a.constraint_name = b.constraint_name
and b.constraint_type in ( 'P', 'U', 'R' )
group by a.table_name, a.constraint_name ) parent
where child.parent_cons_name = parent.parent_cons_name
and child.child_tname = upper('YOUR TABLE NAME HERE')
LOOP
dbdata.extend(i);
dbdata(i) := cdrl5.dbconstraint_documents_rec(cns_rec.pparent_cons_name,cns_rec.clchild_tname,cns_rec.pparent_tname,cns_rec.pparent_columns,cns_rec.pparent_cons_type);
--dbdata(i) := '';
-- dbdata(i) := dbconstraint_rec('test','test','test','test');
--v_sql :=
-- dbdata(i).constraint_name;
i := i+1;
END LOOP;
FOR d IN 1..dbdata.COUNT
LOOP
IF dbdata(d).constraint_name IS NULL
THEN
dbdata.delete(d);
END IF;
END LOOP;
-- dbdata.delete;
return dbdata;
END;
Second part is code that is in trigger of table you are inserting into. Note that you have to store the table name/column name(that make up the constraint)/actual form values into pl/sql table:
DECLARE
v_sql VARCHAR2(32000);
v_literal_value VARCHAR2(100);
v_error_relay VARCHAR2(4000);
v_db_values NUMBER := 1;
v_dup_count NUMBER;
nforeign_key EXCEPTION;
TYPE DupRecordType IS REF CURSOR;
dup_rec_cv DupRecordType;
dbdata DbCons_Documents_Array := DbCons_Documents_Array(cdrl5.dbconstraint_documents_rec(null,null,null,null,null));
TYPE tokenTableType is TABLE of varchar2(4000) -- table for Stringtoken
index by binary_integer;
tokenChar VARCHAR2(4000) := '," ';
tokens tokenTableType;
vCnt integer := 1;
myLine varchar2(4000) := null;
Line varchar2(4000) := null;
vPos integer := 1;
TYPE form_rec IS RECORD
table_name VARCHAR2(100),
db_column VARCHAR2(100),
db_col_value VARCHAR2(1000)
TYPE form_type IS TABLE OF form_rec
INDEX BY binary_integer;
web_form_array form_type;
BEGIN
dbdata.DELETE;
-- IF :new.DOC_ID IS NOT NULL
-- THEN
NOTE: Load the below table(with values specified) for each table constraint
web_form_array(v_db_values).table_name :=
'YOUR TABLE NAME';
web_form_array(v_db_values).db_column :=
'YOUR FIELD NAME';
web_form_array(v_db_values).db_col_value :=
:new.;
v_db_values := v_db_values +1;
FOR cns_rec IN(select *
from TABLE ( cast( documents_cons_dml() as DbCons_documents_Array ))
LOOP
line :=
cns_rec.constraint_where;
v_sql := 'SELECT count(*) FROM '||cns_rec.constraint_column;
IF INSTR(line,',',1,1) <= 0
THEN
FOR find_web_frm_val IN 1..web_form_array.COUNT
LOOP
IF cns_rec.table_name = web_form_array(find_web_frm_val).table_name
AND replace(line,'"','') = web_form_array(find_web_frm_val).db_column
THEN
v_literal_value :=
CONCAT(CONCAT('''',web_form_array(find_web_frm_val).db_col_value),'''');
v_sql := v_sql||' WHERE '||' '||web_form_array(find_web_frm_val).db_column||' = '||v_literal_value;
END IF;
END LOOP;
ELSE
while (vPos <= length(line))
loop
if (length(replace(tokenChar,substr(line, vPos, 1), '')) = length(tokenChar))
then
myLine := myLine || substr(line, vPos, 1);
elsif (myLine is not NULL) then
tokens(vCnt) := myLine;
FOR find_web_frm_val IN 1..v_db_values
LOOP
IF cns_rec.table_name = web_form_array(find_web_frm_val).table_name
AND MYLine = web_form_array(find_web_frm_val).db_column
THEN
v_literal_value :=
CONCAT(CONCAT('''',web_form_array(find_web_frm_val).db_col_value),'''');
END IF;
end loop;
IF vCnt = 1
THEN
v_sql := v_sql||' WHERE '||' '||myLine||' = '||v_literal_value;
ELSE
v_sql := v_sql||' AND '||' '||myLine||' = '||v_literal_value;
END IF;
myLine := null;
vCnt := vCnt + 1;
end if;
vPos := vPos + 1;
end loop;
if (myLine is not NULL) then
tokens(vCnt) := myLine;
end if;
vCnt := 1;
vPos := 1;
END IF;
OPEN dup_rec_cv FOR v_sql;
FETCH dup_rec_cv
INTO v_dup_count;
CLOSE dup_rec_cv;
IF cns_rec.column_position = 'R'
THEN
IF v_dup_count <= 0
THEN
v_error_relay :=
'The form field value for Database Column '||' '||line||' '||' that was entered does not exist';
RAISE nforeign_key;
END IF;
ELSIF cns_rec.column_position = 'U'
THEN
IF v_dup_count > 0
THEN
RAISE DUP_VAL_ON_INDEX;
END IF;
END IF;
-- commit_trans(v_dup_count);
-- INSERT INTO test
-- values(line||' '||INSTR(line,',',1,1));
-- VALUES(cns_rec.constraint_name||' '||cns_rec.table_name||' '||cns_rec.constraint_column||' '||cns_rec.constraint_where);
-- values(v_sql||' '||vPos||' '||length(line));
-- VALUES(web_form_array(i).table_name||' '||CONCAT(CONCAT('''',web_form_array(i).db_col_value),'''')||' '||i);
--commit;
-- i := i+1;
END LOOP;
EXCEPTION
WHEN DUP_VAL_ON_INDEX
THEN
raise_application_error(-20101, 'Attempted to update duplicate. Cannot update '||:new.);
WHEN nforeign_key
THEN raise_application_error(-20101, v_error_relay||' '||' YOUR MESSAGE HERE '||:new.);
END;
Mark:
Ordinarily, I not really a critical guy, but that thing is such a mess that I have to comment. I won't mention the complete lack of bind variables (which leads to the shared pool and hard parsing concerns), but as posted it won't even compile. I had some time to kill, so.
For starters, the big query in your function gets:
ORA-01467: sort key too long
on my 9.2.0.6 instance with 16K blocksize, and on my 9.2.0.1 instance with an 8K blocksize. Interestingly, it does work on my 8.1.7.4 instance with 8K blocks. So, I had to limit it to 15 columns.
You give no function name at all. Based on the trigger code, I assume the function should be documents_cons_dml. I also added a paramter to pass the table name since one could conceivably have more than one table in an application.
I also took the liberty of fixing your extend problem. In your code, you extend the array by one in the first iteration through the loop, by two in the second and so on. Which is why you need the delete loop at the end.
There is no definition for the DbCons_documents_Array that the function returns, so I assumed something like:
SQL> CREATE TYPE dbconstraint_documents_rec AS OBJECT (
2 constraint_name VARCHAR2(30),
3 table_name VARCHAR2(30),
4 constraint_column VARCHAR2(30),
5 constraint_where VARCHAR2(4000),
6 column_position VARCHAR2(1) );
7 /
Type created.
SQL> CREATE TYPE DbCons_documents_Array AS
2 VARRAY(50) OF dbconstraint_documents_rec;
3 /
Type created.I used the names that you used in the trigger, although the names don't seem to match with the column contents, must be code re-use.
So, now the function looks like:
SQL> CREATE FUNCTION documents_cons_dml (p_table_name IN VARCHAR2)
2 RETURN DbCons_documents_Array AS
3
4 dbdata DbCons_documents_Array := DbCons_documents_Array();
5 i NUMBER := 1;
6 BEGIN
7 FOR cns_rec IN(SELECT child.child_cons_name clchild_cons_name,
8 child.parent_cons_name clparent_cons_name,
9 child.child_columns clchild_columns,
10 parent.parent_cons_name pparent_cons_name,
11 parent.parent_tname pparent_tname,
12 child.child_tname clchild_tname,
13 CONCAT(CONCAT('"',REPLACE(REPLACE(parent.parent_columns,'"',''),'''','')),'"') pparent_columns,
14 child.parent_cons_type pparent_cons_type
15 FROM (SELECT a.table_name child_tname,
16 a.constraint_name child_cons_name,
17 NVL(b.r_constraint_name,a.constraint_name) parent_cons_name,
18 b.constraint_type parent_cons_type,
19 MAX(DECODE(position, 1, '"'||column_name||'"',NULL)) ||
20 MAX(DECODE(position, 2,', "'||column_name||'"',NULL)) ||
21 MAX(DECODE(position, 3,', "'||column_name||'"',NULL)) ||
22 MAX(DECODE(position, 4,', "'||column_name||'"',NULL)) ||
23 MAX(DECODE(position, 5,', "'||column_name||'"',NULL)) ||
24 MAX(DECODE(position, 6,', "'||column_name||'"',NULL)) ||
25 MAX(DECODE(position, 7,', "'||column_name||'"',NULL)) ||
26 MAX(DECODE(position, 8,', "'||column_name||'"',NULL)) ||
27 MAX(DECODE(position, 9,', "'||column_name||'"',NULL)) ||
28 MAX(DECODE(position,10,', "'||column_name||'"',NULL)) ||
29 MAX(DECODE(position,11,', "'||column_name||'"',NULL)) ||
30 MAX(DECODE(position,12,', "'||column_name||'"',NULL)) ||
31 MAX(DECODE(position,13,', "'||column_name||'"',NULL)) ||
32 MAX(DECODE(position,14,', "'||column_name||'"',NULL)) ||
33 MAX(DECODE(position,15,', "'||column_name||'"',NULL)) child_columns
34 FROM user_cons_columns a, user_constraints b
35 WHERE a.constraint_name = b.constraint_name and
36 b.constraint_type IN ( 'U', 'R' )
37 GROUP BY a.table_name, a.constraint_name,
38 b.r_constraint_name,b.constraint_type ) child,
39 (SELECT a.constraint_name parent_cons_name,
40 a.table_name parent_tname,
41 MAX(DECODE(position, 1, '"'||column_name||'"',NULL)) ||
42 MAX(DECODE(position, 2,', "'||column_name||'"',NULL)) ||
43 MAX(DECODE(position, 3,', "'||column_name||'"',NULL)) ||
44 MAX(DECODE(position, 4,', "'||column_name||'"',NULL)) ||
45 MAX(DECODE(position, 5,', "'||column_name||'"',NULL)) ||
46 MAX(DECODE(position, 6,', "'||column_name||'"',NULL)) ||
47 MAX(DECODE(position, 7,', "'||column_name||'"',NULL)) ||
48 MAX(DECODE(position, 8,', "'||column_name||'"',NULL)) ||
49 MAX(DECODE(position, 9,', "'||column_name||'"',NULL)) ||
50 MAX(DECODE(position,10,', "'||column_name||'"',NULL)) ||
51 MAX(DECODE(position,11,', "'||column_name||'"',NULL)) ||
52 MAX(DECODE(position,12,', "'||column_name||'"',NULL)) ||
53 MAX(DECODE(position,13,', "'||column_name||'"',NULL)) ||
54 MAX(DECODE(position,14,', "'||column_name||'"',NULL)) ||
55 MAX(DECODE(position,15,', "'||column_name||'"',NULL)) parent_columns
56 FROM user_cons_columns a, user_constraints b
57 WHERE a.constraint_name = b.constraint_name and
58 b.constraint_type IN ( 'P', 'U', 'R' )
59 GROUP BY a.table_name, a.constraint_name ) parent
60 WHERE child.parent_cons_name = parent.parent_cons_name and
61 child.child_tname = upper(p_table_name)) LOOP
62 dbdata.extend;
63 dbdata(i) := dbconstraint_documents_rec(cns_rec.pparent_cons_name,
64 cns_rec.clchild_tname,
65 cns_rec.pparent_tname,
66 cns_rec.pparent_columns,
67 cns_rec.pparent_cons_type);
68 i := i+1;
69 END LOOP;
70 RETURN dbdata;
71 END;
72 /
Function created.
SQL> CREATE TABLE t (ID NUMBER PRIMARY KEY, descr VARCHAR2(10));
Table created.
SQL> CREATE TABLE t1 (idt1 NUMBER PRIMARY KEY, descr VARCHAR2(10));
Table created.
SQL> ALTER TABLE t ADD CONSTRAINT t_fk
2 FOREIGN KEY (id) REFERENCES t1 (idt1);
Table altered.Now for the trigger. Once I got rid of the schema owner cdrl5 in the dbconstraint_documents_rec call it actually compiled first time. So, my trigger looks like:
SQL> CREATE OR REPLACE TRIGGER t_bi
2 BEFORE INSERT ON t
3 FOR EACH ROW
4 DECLARE
5 v_sql VARCHAR2(32000);
6 v_literal_value VARCHAR2(100);
7 v_error_relay VARCHAR2(4000);
8 v_db_values NUMBER := 1;
9 v_dup_count NUMBER;
10 nforeign_key EXCEPTION;
11
12 TYPE DupRecordType IS REF CURSOR;
13 dup_rec_cv DupRecordType;
14
15 dbdata DbCons_Documents_Array := DbCons_Documents_Array(dbconstraint_documents_rec(null,null,null,null,null));
16
17 TYPE tokenTableType IS TABLE OF VARCHAR2(4000) INDEX BY BINARY_INTEGER;
18 tokenChar VARCHAR2(4000) := '," ';
19 tokens tokenTableType;
20 vCnt INTEGER := 1;
21 myLine VARCHAR2(4000) := NULL;
22 Line VARCHAR2(4000) := NULL;
23 vPos INTEGER := 1;
24
25 TYPE form_rec IS RECORD (
26 table_name VARCHAR2(100),
27 db_column VARCHAR2(100),
28 db_col_value VARCHAR2(1000));
29
30 TYPE form_type IS TABLE OF form_rec INDEX BY BINARY_INTEGER;
31 web_form_array form_type;
32
33 BEGIN
34 dbdata.DELETE;
35 -- NOTE: Load the below table(with values specified) for each table constraint
36
37 web_form_array(v_db_values).table_name := 'T';
38 web_form_array(v_db_values).db_column := 'ID';
39 web_form_array(v_db_values).db_col_value := :new.ID;
40 v_db_values := v_db_values +1;
41
42 FOR cns_rec IN(SELECT *
43 FROM TABLE ( CAST(documents_cons_dml('T') AS DbCons_documents_Array ))) LOOP
44 line := cns_rec.constraint_where;
45 v_sql := 'SELECT count(*) FROM '||cns_rec.constraint_column;
46 IF INSTR(line,',',1,1) <= 0 THEN
47 FOR find_web_frm_val IN 1 .. web_form_array.COUNT LOOP
48 IF cns_rec.table_name = web_form_array(find_web_frm_val).table_name AND
49 REPLACE(line,'"','') = web_form_array(find_web_frm_val).db_column THEN
50
51 v_literal_value :=CONCAT(CONCAT('''',web_form_array(find_web_frm_val).db_col_value),'''');
52 v_sql := v_sql||' WHERE '||' '||web_form_array(find_web_frm_val).db_column||' = '||v_literal_value;
53 END IF;
54 END LOOP;
55 ELSE
56 WHILE (vPos <= LENGTH(line)) LOOP
57 IF (LENGTH(REPLACE(tokenChar,substr(line, vPos, 1), '')) = LENGTH(tokenChar)) THEN
58 myLine := myLine || substr(line, vPos, 1);
59 ELSIF (myLine IS NOT NULL) THEN
60 tokens(vCnt) := myLine;
61 FOR find_web_frm_val IN 1 .. v_db_values LOOP
62 IF cns_rec.table_name = web_form_array(find_web_frm_val).table_name AND
63 MYLine = web_form_array(find_web_frm_val).db_column THEN
64 v_literal_value := CONCAT(CONCAT('''',web_form_array(find_web_frm_val).db_col_value),'''');
65 END IF;
66 END LOOP;
67 IF vCnt = 1 THEN
68 v_sql := v_sql||' WHERE '||' '||myLine||' = '||v_literal_value;
69 ELSE
70 v_sql := v_sql||' AND '||' '||myLine||' = '||v_literal_value;
71 END IF;
72 myLine := null;
73 vCnt := vCnt + 1;
74 END IF;
75 vPos := vPos + 1;
76 END LOOP;
77
78 IF (myLine IS NOT NULL) THEN
79 tokens(vCnt) := myLine;
80 END IF;
81 vCnt := 1;
82 vPos := 1;
83 END IF;
84
85 OPEN dup_rec_cv FOR v_sql;
86 FETCH dup_rec_cv INTO v_dup_count;
87 CLOSE dup_rec_cv;
88 IF cns_rec.column_position = 'R' THEN
89 IF v_dup_count <= 0 THEN
90 v_error_relay := 'The form field value for Database Column '||' '||line||' '||' that was entered does not exist';
91 RAISE nforeign_key;
92 END IF;
93 ELSIF cns_rec.column_position = 'U' THEN
94 IF v_dup_count > 0 THEN
95 RAISE DUP_VAL_ON_INDEX;
96 END IF;
97 END IF;
98 END LOOP;
99 EXCEPTION
100 WHEN DUP_VAL_ON_INDEX THEN
101 raise_application_error(-20101, 'Attempted to update duplicate. Cannot update '||:new.ID);
102 WHEN nforeign_key THEN
103 raise_application_error(-20101, v_error_relay||' '||' YOUR MESSAGE HERE '||:new.ID);
104 END;
105 /
Trigger created.So, lets try this puppy out.
SQL> INSERT INTO t1 VALUES (1, 'T1 ONE');
1 row created.
SQL> COMMIT;
Commit complete.I want at least one valid value to make sure I can actually insert something without dying on the trigger.
SQL> INSERT INTO t VALUES (1, 'T One');
1 row created.
SQL> COMMIT;
Commit complete.Which we can. Now lets test the Primary Key.
SQL> INSERT INTO t VALUES (1, 'T One');
INSERT INTO t VALUES (1, 'T One')
ERROR at line 1:
ORA-00001: unique constraint (OPS$ORACLE.SYS_C0027113) violatedOOPS, that's Oracle's message. Well, maybe it's because you are only checking cns_rec.column_position for R or U and my constraint is a P, and by the way, your function does not return the Primary Key for the table passed at all.
So, lets try the foreign key:
SQL> INSERT INTO t VALUES (2, 'T Two');
INSERT INTO t VALUES (2, 'T Two')
ERROR at line 1:
ORA-02291: integrity constraint (OPS$ORACLE.T_FK) violated - parent key not foundOOPS. So, for every valid insert I am doing a huge amount of extra work, and I still get Oracle's errors when it's wrong. If I have screwed something up in the set-up, please feel free to post a working example exactly as I did here.
John
Similar Messages
-
To automate the SQL scripts using PLSQL Code
Hi All,
I have 20 database server (11.2.0.3) hosted on unix and Windows platforms.
Every day I have to kill inactive sessions from all the these 20 database servers. So I have made a below script::
connect sys/&&sys_password@&&tns_database_name as sysdba
SPOOL E:\DELETE_INACTIVE_SESSIONS.SQL
set PAGESIZE 1000
set LIN 5000
SET ECHO OFF;
SET FEEDBACK OFF;
SET HEADING OFF;
select 'alter system kill session '||'`'||SID||','||SERIAL#||'`'||' immediate;' from v$session where status='INACTIVE' and username in ('OSS_DICTIONARY','ADMINISTRATOR');
SPOOL OFF;
@@E:\DELETE_INACTIVE_SESSIONS.SQL
Is there any way so that this execution of script can be automated in PLSQL code for 20 servers so and that code could be put in batch file for execution(i.e. can be execute through batch file from my windows laptop).
ThanksShrma wrote:
Is there no way to handle the sql scripts in PLSQL code?
Well, remember that PL/SQL is executed on a specific server by a certain user so you are already connected when executing a PL/SQL code.
You could actually use a SQL Plus script to connect to different servers using connect and run your script.
i.e.:
SQL> connect sys/pwd_server1@db_server1
SQL> @killinactive.sql
SQL> connect sys/pwd_server2@db_server2
SQL> @killinactive.sql
But it does not make so much difference with my previous solution.
Please explain exactly what you would like to do.
Regards.
Al -
PL/SQL 101 : Exception Handling
Frequently I see questions and issues around the use of Exception/Error Handling in PL/SQL. More often than not the issue comes from the questioners misunderstanding about how PL/SQL is constructed and executed, so I thought I'd write a small article covering the key concepts to give a clear picture of how it all hangs together. (Note: the examples are just showing examples of the exception handling structure, and should not be taken as truly valid code for ways of handling things)
Exception Handling
Contents
1. Understanding Execution Blocks (part 1)
2. Execution of the Execution Block
3. Exceptions
4. Understanding Execution Blocks (part 2)
5. How to continue exection of statements after an exception
6. User defined exceptions
7. Line number of exception
8. Exceptions within code within the exception block
1. Understanding Execution Blocks (part 1)
The first thing that one needs to understand is almost taking us back to the basics of PL/SQL... how a PL/SQL execution block is constructed.
Essentially an execution block is made of 3 sections...
+---------------------------+
| Declaration Section |
+---------------------------+
| Statements Section |
+---------------------------+
| Exception Section |
+---------------------------+
The Declaration section is the part defined between the PROCEDURE/FUNCTION header or the DECLARE keyword (for anonymous blocks) and the BEGIN keyword. (Optional section)
The Statements section is where your code goes and lies between the BEGIN keyword and the EXCEPTION keyword (or END keyword if there is no EXCEPTION section). (Mandatory section)
The Exception section is where any exception handling goes and lies between the EXCEPTION keyword at the END keyword. (Optional section)
Example of an anonymous block...
DECLARE
.. declarative statements go here ..
BEGIN
.. code statements go here ..
EXCEPTION
.. exception handlers go here ..
END;
Example of a procedure/function block...
[CREATE OR REPLACE] (PROCEDURE|FUNCTION) <proc or fn name> [(<parameters>)] [RETURN <datatype>] (IS|AS)
.. declarative statements go here ..
BEGIN
.. code statements go here ..
EXCEPTION
.. exception handlers go here ..
END;
(Note: The same can also be done for packages, but let's keep it simple)
2. Execution of the Execution Block
This may seem a simple concept, but it's surprising how many people have issues showing they haven't grasped it. When an Execution block is entered, the declaration section is processed, creating a scope of variables, types , cursors, etc. to be visible to the execution block and then execution enters into the Statements section. Each statment in the statements section is executed in turn and when the execution completes the last statment the execution block is exited back to whatever called it.
3. Exceptions
Exceptions generally happen during the execution of statements in the Statements section. When an exception happens the execution of statements jumps immediately into the exception section. In this section we can specify what exceptions we wish to 'capture' or 'trap' and do one of the two following things...
(Note: The exception section still has access to all the declared items in the declaration section)
3.i) Handle the exception
We do this when we recognise what the exception is (most likely it's something we expect to happen) and we have a means of dealing with it so that our application can continue on.
Example...
(without the exception handler the exception is passed back to the calling code, in this case SQL*Plus)
SQL> ed
Wrote file afiedt.buf
1 declare
2 v_name VARCHAR2(20);
3 begin
4 select ename
5 into v_name
6 from emp
7 where empno = &empno;
8 dbms_output.put_line(v_name);
9* end;
SQL> /
Enter value for empno: 123
old 7: where empno = &empno;
new 7: where empno = 123;
declare
ERROR at line 1:
ORA-01403: no data found
ORA-06512: at line 4
(with an exception handler, we capture the exception, handle it how we want to, and the calling code is happy that there is no error for it to report)
SQL> ed
Wrote file afiedt.buf
1 declare
2 v_name VARCHAR2(20);
3 begin
4 select ename
5 into v_name
6 from emp
7 where empno = &empno;
8 dbms_output.put_line(v_name);
9 exception
10 when no_data_found then
11 dbms_output.put_line('There is no employee with this employee number.');
12* end;
SQL> /
Enter value for empno: 123
old 7: where empno = &empno;
new 7: where empno = 123;
There is no employee with this employee number.
PL/SQL procedure successfully completed.
3.ii) Raise the exception
We do this when:-
a) we recognise the exception, handle it but still want to let the calling code know that it happened
b) we recognise the exception, wish to log it happened and then let the calling code deal with it
c) we don't recognise the exception and we want the calling code to deal with it
Example of b)
SQL> ed
Wrote file afiedt.buf
1 declare
2 v_name VARCHAR2(20);
3 v_empno NUMBER := &empno;
4 begin
5 select ename
6 into v_name
7 from emp
8 where empno = v_empno;
9 dbms_output.put_line(v_name);
10 EXCEPTION
11 WHEN no_data_found THEN
12 INSERT INTO sql_errors (txt)
13 VALUES ('Search for '||v_empno||' failed.');
14 COMMIT;
15 RAISE;
16* end;
SQL> /
Enter value for empno: 123
old 3: v_empno NUMBER := &empno;
new 3: v_empno NUMBER := 123;
declare
ERROR at line 1:
ORA-01403: no data found
ORA-06512: at line 15
SQL> select * from sql_errors;
TXT
Search for 123 failed.
SQL>
Example of c)
SQL> ed
Wrote file afiedt.buf
1 declare
2 v_name VARCHAR2(20);
3 v_empno NUMBER := &empno;
4 begin
5 select ename
6 into v_name
7 from emp
8 where empno = v_empno;
9 dbms_output.put_line(v_name);
10 EXCEPTION
11 WHEN no_data_found THEN
12 INSERT INTO sql_errors (txt)
13 VALUES ('Search for '||v_empno||' failed.');
14 COMMIT;
15 RAISE;
16 WHEN others THEN
17 RAISE;
18* end;
SQL> /
Enter value for empno: 'ABC'
old 3: v_empno NUMBER := &empno;
new 3: v_empno NUMBER := 'ABC';
declare
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: character to number conversion error
ORA-06512: at line 3
SQL> select * from sql_errors;
TXT
Search for 123 failed.
SQL>
As you can see from the sql_errors log table, no log was written so the WHEN others exception was the exception that raised the error to the calling code (SQL*Plus)
4. Understanding Execution Blocks (part 2)
Ok, so now we understand the very basics of an execution block and what happens when an exception happens. Let's take it a step further...
Execution blocks are not just a single simple block in most cases. Often, during our statements section we have a need to call some reusable code and we do that by calling a procedure or function. Effectively this nests the procedure or function's code as another execution block within the current statement section so, in terms of execution, we end up with something like...
+---------------------------------+
| Declaration Section |
+---------------------------------+
| Statements Section |
| . |
| +---------------------------+ |
| | Declaration Section | |
| +---------------------------+ |
| | Statements Section | |
| +---------------------------+ |
| | Exception Section | |
| +---------------------------+ |
| . |
+---------------------------------+
| Exception Section |
+---------------------------------+
Example... (Note: log_trace just writes some text to a table for tracing)
SQL> create or replace procedure a as
2 v_dummy NUMBER := log_trace('Procedure A''s Declaration Section');
3 begin
4 v_dummy := log_trace('Procedure A''s Statement Section');
5 v_dummy := 1/0; -- cause an exception
6 exception
7 when others then
8 v_dummy := log_trace('Procedure A''s Exception Section');
9 raise;
10 end;
11 /
Procedure created.
SQL> create or replace procedure b as
2 v_dummy NUMBER := log_trace('Procedure B''s Declaration Section');
3 begin
4 v_dummy := log_trace('Procedure B''s Statement Section');
5 a; -- HERE the execution passes to the declare/statement/exception sections of A
6 exception
7 when others then
8 v_dummy := log_trace('Procedure B''s Exception Section');
9 raise;
10 end;
11 /
Procedure created.
SQL> exec b;
BEGIN b; END;
ERROR at line 1:
ORA-01476: divisor is equal to zero
ORA-06512: at "SCOTT.B", line 9
ORA-06512: at line 1
SQL> select * from code_trace;
TXT
Procedure B's Declaration Section
Procedure B's Statement Section
Procedure A's Declaration Section
Procedure A's Statement Section
Procedure A's Exception Section
Procedure B's Exception Section
6 rows selected.
SQL>
Likewise, execution blocks can be nested deeper and deeper.
5. How to continue exection of statements after an exception
One of the common questions asked is how to return execution to the statement after the one that created the exception and continue on.
Well, firstly, you can only do this for statements you expect to raise an exception, such as when you want to check if there is no data found in a query.
If you consider what's been shown above you could put any statement you expect to cause an exception inside it's own procedure or function with it's own exception section to handle the exception without raising it back to the calling code. However, the nature of procedures and functions is really to provide a means of re-using code, so if it's a statement you only use once it seems a little silly to go creating individual procedures for these.
Instead, you nest execution blocks directly, to give the same result as shown in the diagram at the start of part 4 of this article.
SQL> ed
Wrote file afiedt.buf
1 create or replace procedure b (p_empno IN VARCHAR2) as
2 v_dummy NUMBER := log_trace('Procedure B''s Declaration Section');
3 begin
4 v_dummy := log_trace('Procedure B''s Statement Section');
5 -- Here we start another execution block nested in the first one...
6 declare
7 v_dummy NUMBER := log_trace('Nested Block Declaration Section');
8 begin
9 v_dummy := log_trace('Nested Block Statement Section');
10 select empno
11 into v_dummy
12 from emp
13 where empno = p_empno; -- Note: the parameters and variables from
parent execution block are available to use!
14 exception
15 when no_data_found then
16 -- This is an exception we can handle so we don't raise it
17 v_dummy := log_trace('No employee was found');
18 v_dummy := log_trace('Nested Block Exception Section - Exception Handled');
19 when others then
20 -- Other exceptions we can't handle so we raise them
21 v_dummy := log_trace('Nested Block Exception Section - Exception Raised');
22 raise;
23 end;
24 -- ...Here endeth the nested execution block
25 -- As the nested block handled it's exception we come back to here...
26 v_dummy := log_trace('Procedure B''s Statement Section Continued');
27 exception
28 when others then
29 -- We'll only get to here if an unhandled exception was raised
30 -- either in the nested block or in procedure b's statement section
31 v_dummy := log_trace('Procedure B''s Exception Section');
32 raise;
33* end;
SQL> /
Procedure created.
SQL> exec b(123);
PL/SQL procedure successfully completed.
SQL> select * from code_trace;
TXT
Procedure B's Declaration Section
Procedure B's Statement Section
Nested Block Declaration Section
Nested Block Statement Section
No employee was found
Nested Block Exception Section - Exception Handled
Procedure B's Statement Section Continued
7 rows selected.
SQL> truncate table code_trace;
Table truncated.
SQL> exec b('ABC');
BEGIN b('ABC'); END;
ERROR at line 1:
ORA-01722: invalid number
ORA-06512: at "SCOTT.B", line 32
ORA-06512: at line 1
SQL> select * from code_trace;
TXT
Procedure B's Declaration Section
Procedure B's Statement Section
Nested Block Declaration Section
Nested Block Statement Section
Nested Block Exception Section - Exception Raised
Procedure B's Exception Section
6 rows selected.
SQL>
You can see from this that, very simply, the code that we expected may have an exception was able to either handle the exception and return to the outer execution block to continue execution, or if an unexpected exception occurred then it was able to be raised up to the outer exception section.
6. User defined exceptions
There are three sorts of 'User Defined' exceptions. There are logical situations (e.g. business logic) where, for example, certain criteria are not met to complete a task, and there are existing Oracle errors that you wish to give a name to in order to capture them in the exception section. The third is raising your own exception messages with our own exception numbers. Let's look at the first one...
Let's say I have tables which detail stock availablility and reorder levels...
SQL> select * from reorder_level;
ITEM_ID STOCK_LEVEL
1 20
2 20
3 10
4 2
5 2
SQL> select * from stock;
ITEM_ID ITEM_DESC STOCK_LEVEL
1 Pencils 10
2 Pens 2
3 Notepads 25
4 Stapler 5
5 Hole Punch 3
SQL>
Now, our Business has told the administrative clerk to check stock levels and re-order anything that is below the re-order level, but not to hold stock of more than 4 times the re-order level for any particular item. As an IT department we've been asked to put together an application that will automatically produce the re-order documents upon the clerks request and, because our company is so tight-ar*ed about money, they don't want to waste any paper with incorrect printouts so we have to ensure the clerk can't order things they shouldn't.
SQL> ed
Wrote file afiedt.buf
1 create or replace procedure re_order(p_item_id NUMBER, p_quantity NUMBER) is
2 cursor cur_stock_reorder is
3 select s.stock_level
4 ,r.stock_level as reorder_level
5 ,(r.stock_level*4) as reorder_limit
6 from stock s join reorder_level r on (s.item_id = r.item_id)
7 where s.item_id = p_item_id;
8 --
9 v_stock cur_stock_reorder%ROWTYPE;
10 begin
11 OPEN cur_stock_reorder;
12 FETCH cur_stock_reorder INTO v_stock;
13 IF cur_stock_reorder%NOTFOUND THEN
14 RAISE no_data_found;
15 END IF;
16 CLOSE cur_stock_reorder;
17 --
18 IF v_stock.stock_level >= v_stock.reorder_level THEN
19 -- Stock is not low enough to warrant an order
20 DBMS_OUTPUT.PUT_LINE('Stock has not reached re-order level yet!');
21 ELSE
22 IF v_stock.stock_level + p_quantity > v_stock.reorder_limit THEN
23 -- Required amount is over-ordering
24 DBMS_OUTPUT.PUT_LINE('Quantity specified is too much. Max for this item: '
||to_char(v_stock.reorder_limit-v_stock.stock_level));
25 ELSE
26 DBMS_OUTPUT.PUT_LINE('Order OK. Printing Order...');
27 -- Here goes our code to print the order
28 END IF;
29 END IF;
30 --
31 exception
32 WHEN no_data_found THEN
33 CLOSE cur_stock_reorder;
34 DBMS_OUTPUT.PUT_LINE('Invalid Item ID.');
35* end;
SQL> /
Procedure created.
SQL> exec re_order(10,100);
Invalid Item ID.
PL/SQL procedure successfully completed.
SQL> exec re_order(3,40);
Stock has not reached re-order level yet!
PL/SQL procedure successfully completed.
SQL> exec re_order(1,100);
Quantity specified is too much. Max for this item: 70
PL/SQL procedure successfully completed.
SQL> exec re_order(2,50);
Order OK. Printing Order...
PL/SQL procedure successfully completed.
SQL>
Ok, so that code works, but it's a bit messy with all those nested IF statements. Is there a cleaner way perhaps? Wouldn't it be nice if we could set up our own exceptions...
SQL> ed
Wrote file afiedt.buf
1 create or replace procedure re_order(p_item_id NUMBER, p_quantity NUMBER) is
2 cursor cur_stock_reorder is
3 select s.stock_level
4 ,r.stock_level as reorder_level
5 ,(r.stock_level*4) as reorder_limit
6 from stock s join reorder_level r on (s.item_id = r.item_id)
7 where s.item_id = p_item_id;
8 --
9 v_stock cur_stock_reorder%ROWTYPE;
10 --
11 -- Let's declare our own exceptions for business logic...
12 exc_not_warranted EXCEPTION;
13 exc_too_much EXCEPTION;
14 begin
15 OPEN cur_stock_reorder;
16 FETCH cur_stock_reorder INTO v_stock;
17 IF cur_stock_reorder%NOTFOUND THEN
18 RAISE no_data_found;
19 END IF;
20 CLOSE cur_stock_reorder;
21 --
22 IF v_stock.stock_level >= v_stock.reorder_level THEN
23 -- Stock is not low enough to warrant an order
24 RAISE exc_not_warranted;
25 END IF;
26 --
27 IF v_stock.stock_level + p_quantity > v_stock.reorder_limit THEN
28 -- Required amount is over-ordering
29 RAISE exc_too_much;
30 END IF;
31 --
32 DBMS_OUTPUT.PUT_LINE('Order OK. Printing Order...');
33 -- Here goes our code to print the order
34 --
35 exception
36 WHEN no_data_found THEN
37 CLOSE cur_stock_reorder;
38 DBMS_OUTPUT.PUT_LINE('Invalid Item ID.');
39 WHEN exc_not_warranted THEN
40 DBMS_OUTPUT.PUT_LINE('Stock has not reached re-order level yet!');
41 WHEN exc_too_much THEN
42 DBMS_OUTPUT.PUT_LINE('Quantity specified is too much. Max for this item: '
||to_char(v_stock.reorder_limit-v_stock.stock_level));
43* end;
SQL> /
Procedure created.
SQL> exec re_order(10,100);
Invalid Item ID.
PL/SQL procedure successfully completed.
SQL> exec re_order(3,40);
Stock has not reached re-order level yet!
PL/SQL procedure successfully completed.
SQL> exec re_order(1,100);
Quantity specified is too much. Max for this item: 70
PL/SQL procedure successfully completed.
SQL> exec re_order(2,50);
Order OK. Printing Order...
PL/SQL procedure successfully completed.
SQL>
That's better. And now we don't have to use all those nested IF statements and worry about it accidently getting to code that will print the order out as, once one of our user defined exceptions is raised, execution goes from the Statements section into the Exception section and all handling of errors is done in one place.
Now for the second sort of user defined exception...
A new requirement has come in from the Finance department who want to have details shown on the order that show a re-order 'indicator' based on the formula ((maximum allowed stock - current stock)/re-order quantity), so this needs calculating and passing to the report...
SQL> ed
Wrote file afiedt.buf
1 create or replace procedure re_order(p_item_id NUMBER, p_quantity NUMBER) is
2 cursor cur_stock_reorder is
3 select s.stock_level
4 ,r.stock_level as reorder_level
5 ,(r.stock_level*4) as reorder_limit
6 ,(((r.stock_level*4)-s.stock_level)/p_quantity) as finance_factor
7 from stock s join reorder_level r on (s.item_id = r.item_id)
8 where s.item_id = p_item_id;
9 --
10 v_stock cur_stock_reorder%ROWTYPE;
11 --
12 -- Let's declare our own exceptions for business logic...
13 exc_not_warranted EXCEPTION;
14 exc_too_much EXCEPTION;
15 begin
16 OPEN cur_stock_reorder;
17 FETCH cur_stock_reorder INTO v_stock;
18 IF cur_stock_reorder%NOTFOUND THEN
19 RAISE no_data_found;
20 END IF;
21 CLOSE cur_stock_reorder;
22 --
23 IF v_stock.stock_level >= v_stock.reorder_level THEN
24 -- Stock is not low enough to warrant an order
25 RAISE exc_not_warranted;
26 END IF;
27 --
28 IF v_stock.stock_level + p_quantity > v_stock.reorder_limit THEN
29 -- Required amount is over-ordering
30 RAISE exc_too_much;
31 END IF;
32 --
33 DBMS_OUTPUT.PUT_LINE('Order OK. Printing Order...');
34 -- Here goes our code to print the order, passing the finance_factor
35 --
36 exception
37 WHEN no_data_found THEN
38 CLOSE cur_stock_reorder;
39 DBMS_OUTPUT.PUT_LINE('Invalid Item ID.');
40 WHEN exc_not_warranted THEN
41 DBMS_OUTPUT.PUT_LINE('Stock has not reached re-order level yet!');
42 WHEN exc_too_much THEN
43 DBMS_OUTPUT.PUT_LINE('Quantity specified is too much. Max for this item: '
||to_char(v_stock.reorder_limit-v_stock.stock_level));
44* end;
SQL> /
Procedure created.
SQL> exec re_order(2,40);
Order OK. Printing Order...
PL/SQL procedure successfully completed.
SQL> exec re_order(2,0);
BEGIN re_order(2,0); END;
ERROR at line 1:
ORA-01476: divisor is equal to zero
ORA-06512: at "SCOTT.RE_ORDER", line 17
ORA-06512: at line 1
SQL>
Hmm, there's a problem if the person specifies a re-order quantity of zero. It raises an unhandled exception.
Well, we could put a condition/check into our code to make sure the parameter is not zero, but again we would be wrapping our code in an IF statement and not dealing with the exception in the exception handler.
We could do as we did before and just include a simple IF statement to check the value and raise our own user defined exception but, in this instance the error is standard Oracle error (ORA-01476) so we should be able to capture it inside the exception handler anyway... however...
EXCEPTION
WHEN ORA-01476 THEN
... is not valid. What we need is to give this Oracle error a name.
This is done by declaring a user defined exception as we did before and then associating that name with the error number using the PRAGMA EXCEPTION_INIT statement in the declaration section.
SQL> ed
Wrote file afiedt.buf
1 create or replace procedure re_order(p_item_id NUMBER, p_quantity NUMBER) is
2 cursor cur_stock_reorder is
3 select s.stock_level
4 ,r.stock_level as reorder_level
5 ,(r.stock_level*4) as reorder_limit
6 ,(((r.stock_level*4)-s.stock_level)/p_quantity) as finance_factor
7 from stock s join reorder_level r on (s.item_id = r.item_id)
8 where s.item_id = p_item_id;
9 --
10 v_stock cur_stock_reorder%ROWTYPE;
11 --
12 -- Let's declare our own exceptions for business logic...
13 exc_not_warranted EXCEPTION;
14 exc_too_much EXCEPTION;
15 --
16 exc_zero_quantity EXCEPTION;
17 PRAGMA EXCEPTION_INIT(exc_zero_quantity, -1476);
18 begin
19 OPEN cur_stock_reorder;
20 FETCH cur_stock_reorder INTO v_stock;
21 IF cur_stock_reorder%NOTFOUND THEN
22 RAISE no_data_found;
23 END IF;
24 CLOSE cur_stock_reorder;
25 --
26 IF v_stock.stock_level >= v_stock.reorder_level THEN
27 -- Stock is not low enough to warrant an order
28 RAISE exc_not_warranted;
29 END IF;
30 --
31 IF v_stock.stock_level + p_quantity > v_stock.reorder_limit THEN
32 -- Required amount is over-ordering
33 RAISE exc_too_much;
34 END IF;
35 --
36 DBMS_OUTPUT.PUT_LINE('Order OK. Printing Order...');
37 -- Here goes our code to print the order, passing the finance_factor
38 --
39 exception
40 WHEN exc_zero_quantity THEN
41 DBMS_OUTPUT.PUT_LINE('Quantity of 0 (zero) is invalid.');
42 WHEN no_data_found THEN
43 CLOSE cur_stock_reorder;
44 DBMS_OUTPUT.PUT_LINE('Invalid Item ID.');
45 WHEN exc_not_warranted THEN
46 DBMS_OUTPUT.PUT_LINE('Stock has not reached re-order level yet!');
47 WHEN exc_too_much THEN
48 DBMS_OUTPUT.PUT_LINE('Quantity specified is too much. Max for this item: '
||to_char(v_stock.reorder_limit-v_stock.stock_level));
49* end;
SQL> /
Procedure created.
SQL> exec re_order(2,0);
Quantity of 0 (zero) is invalid.
PL/SQL procedure successfully completed.
SQL>
Lastly, let's look at raising our own exceptions with our own exception numbers...
SQL> ed
Wrote file afiedt.buf
1 create or replace procedure re_order(p_item_id NUMBER, p_quantity NUMBER) is
2 cursor cur_stock_reorder is
3 select s.stock_level
4 ,r.stock_level as reorder_level
5 ,(r.stock_level*4) as reorder_limit
6 ,(((r.stock_level*4)-s.stock_level)/p_quantity) as finance_factor
7 from stock s join reorder_level r on (s.item_id = r.item_id)
8 where s.item_id = p_item_id;
9 --
10 v_stock cur_stock_reorder%ROWTYPE;
11 --
12 exc_zero_quantity EXCEPTION;
13 PRAGMA EXCEPTION_INIT(exc_zero_quantity, -1476);
14 begin
15 OPEN cur_stock_reorder;
16 FETCH cur_stock_reorder INTO v_stock;
17 IF cur_stock_reorder%NOTFOUND THEN
18 RAISE no_data_found;
19 END IF;
20 CLOSE cur_stock_reorder;
21 --
22 IF v_stock.stock_level >= v_stock.reorder_level THEN
23 -- Stock is not low enough to warrant an order
24 [b]RAISE_APPLICATION_ERROR(-20000, 'Stock has not reached re-order level yet!');[/b]
25 END IF;
26 --
27 IF v_stock.stock_level + p_quantity > v_stock.reorder_limit THEN
28 -- Required amount is over-ordering
29its nice article, have put up this one the blog
site,Nah, I don't have time to blog, but if one of the other Ace's/Experts wants to copy it to a blog with reference back to here (and all due credit given ;)) then that's fine by me.
I'd go for a book like "Selected articles by OTN members" or something. Does anybody have a list of links of all those mentioned articles?Just these ones I've bookmarked...
Introduction to regular expressions ... by CD
When your query takes too long ... by Rob van Wijk
How to pipeline a function with a dynamic number of columns? by ascheffer
PL/SQL 101 : Exception Handling by BluShadow -
Unable to get automatic event handling for OK button.
Hello,
I have created a form using creatobject. This form contains an edit control and Search, Cancel buttons. I have set the Search buttons UID to "1" so it can handle the Enter key hit event. Instead its caption changes to Update when i start typing in the edit control and it does not respond to the Enter key hit. Cancel happens when Esc is hit.
My code looks like this -
Dim oCreationParams As SAPbouiCOM.FormCreationParams
oCreationParams = SBO_Application.CreateObject(SAPbouiCOM.BoCreatableObjectType.cot_FormCreationParams)
oCreationParams.UniqueID = "MySearchForm"
oCreationParams.BorderStyle = SAPbouiCOM.BoFormBorderStyle.fbs_Sizable
Dim oForm As SAPbouiCOM.Form = SBO_Application.Forms.AddEx(oCreationParams)
oForm.Visible = True
'// set the form properties
oForm.Title = "Search Form"
oForm.Left = 300
oForm.ClientWidth = 500
oForm.Top = 100
oForm.ClientHeight = 240
'// Adding Items to the form
'// and setting their properties
'// Adding an Ok button
'// We get automatic event handling for
'// the Ok and Cancel Buttons by setting
'// their UIDs to 1 and 2 respectively
oItem = oForm.Items.Add("1", SAPbouiCOM.BoFormItemTypes.it_BUTTON)
oItem.Left = 5
oItem.Width = 65
oItem.Top = oForm.ClientHeight - 30
oItem.Height = 19
oButton = oItem.Specific
oButton.Caption = "Search"
'// Adding a Cancel button
oItem = oForm.Items.Add("2", SAPbouiCOM.BoFormItemTypes.it_BUTTON)
oItem.Left = 75
oItem.Width = 65
oItem.Top = oForm.ClientHeight - 30
oItem.Height = 19
oButton = oItem.Specific
oButton.Caption = "Cancel"
oItem = oForm.Items.Add("NUM", SAPbouiCOM.BoFormItemTypes.it_EDIT)
oItem.Left = 105
oItem.Width = 140
oItem.Top = 20
oItem.Height = 16
Dim oEditText As SAPbouiCOM.EditText = oItem.Specific
What changes do i have to make to get the enter key to work?
Thanks for your help.
Regards,
SheetalHello Felipe,
Thanks for pointing me to the correct direction.
So on refering to the documentation i tried out a few things. But I am still missing something here.
I made the following changes to my code -
oForm.AutoManaged = True
oForm.SupportedModes = 1 ' afm_Ok
oItem = oForm.Items.Add("1", SAPbouiCOM.BoFormItemTypes.it_BUTTON)
oItem.Left = 5
oItem.Width = 65
oItem.Top = oForm.ClientHeight - 30
oItem.Height = 19
oItem.SetAutoManagedAttribute(SAPbouiCOM.BoAutoManagedAttr.ama_Visible, 1, SAPbouiCOM.BoModeVisualBehavior.mvb_Default)
oButton = oItem.Specific
oButton.Caption = "OK"
AND
oForm.Mode = SAPbouiCOM.BoFormMode.fm_OK_MODE
oItem = oForm.Items.Add("1", SAPbouiCOM.BoFormItemTypes.it_BUTTON)
oItem.Left = 5
oItem.Width = 65
oItem.Top = oForm.ClientHeight - 30
oItem.Height = 19
oItem.AffectsFormMode = False
I get the same behaviour OK button changes to update and enter key does not work.
Could you please tell me find what is it that i am doing wrong?
Regards,
Sheetal -
How to show a message in a form 'PL/SQL Button Event Handler'
We need validate the sal of an employee, and if it is bigger the value musts
not be inserted.
We trying a code like the one shown in the note 134312.1 'HOW TO PASS A
PARAMETER FROM A PORTAL FORM TO A STORED PROCEDURE' and it works in the insert event of the insert button (using 'PL/SQL Button Event Handler') and it works, but we need to show a message that says the data wasn't inserted. How can we do this?
The code we used is:
declare
v_deptno scott.emp.deptno%type;
v_empno scott.emp.empno%type;
v_sal scott.emp.sal%type;
mySal scott.emp.sal%type;
v_string varchar2(256);
blk varchar2(10):='DEFAULT';
begin
select sal into mySal from scott.emp where empno=7369;
v_deptno:=p_session.get_value_as_number(p_block_name=>blk,
p_attribute_name=>'A_DEPTNO');
v_empno:=p_session.get_value_as_number(p_block_name=>blk,
p_attribute_name=>'A_EMPNO');
v_sal:=p_session.get_value_as_number(p_block_name=>blk,
p_attribute_name=>'A_SAL');
v_string:='You just inserted empno: '||to_char(v_empno) ||'to deptno ->
'||to_char(v_deptno);
if mySal < v_sal then
doInsert;
else
-- We want to display a message here, when mySal > v_sal
end if;
end;
----------------------------------I did something similar but wasn't using a stored procedure. Couldn't you set a flag variable once you know you're not doing the insert and in the "before displaying the form" section put an IF to check if your flag was set, and if so do an HTP.Print('You are overpaid buddy!');
Then just reset your flag. -
Java.sql.SQLException: statement handle not executed
hello,
i am calling a stored procedure and its returns a REF CURSOR and i am getting intermittent exceptions below,
org.springframework.jdbc.UncategorizedSQLException: Hibernate operation: could not execute query; uncategorized SQLException for SQL [{call
xxxx_pkg(?,?)}]; SQL state [99999]; error code [17144]; statement handle not executed; nested exception is java.sql.SQLException: statement handle not executed
and
org.springframework.jdbc.UncategorizedSQLException: Hibernate operation: could not execute query; uncategorized SQLException for SQL [{call
xxxx_pkg(?,?,?)}]; SQL state [99999]; error code [17009]; Closed Statement; nested exception is java.sql.SQLException: Closed Statement
any clue what could be the issue,
Regards
GGits pretty simple have a java class calling hibernateTemplate's findByNamedQueryAndNamedParam method by passing the procedure name and binding parameters/values, and here is the stack
org.springframework.jdbc.UncategorizedSQLException: Hibernate operation: could not execute query; uncategorized SQLException for SQL [{call
xxx_pkg(?,?)}]; SQL state [99999]; error code [17144]; statement handle not executed; nested exception is java.sql.SQLException: statement handle not executed
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:83)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80)
at org.springframework.orm.hibernate3.HibernateAccessor.convertJdbcAccessException(HibernateAccessor.java:424)
at org.springframework.orm.hibernate3.HibernateAccessor.convertHibernateAccessException(HibernateAccessor.java:410)
at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:411)
at org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374)
at org.springframework.orm.hibernate3.HibernateTemplate.findByNamedQueryAndNamedParam(HibernateTemplate.java:1006)
Caused by: java.sql.SQLException: statement handle not executed
at oracle.jdbc.driver.SQLStateMapping.newSQLException(SQLStateMapping.java:70)
at oracle.jdbc.driver.DatabaseError.newSQLException(DatabaseError.java:112)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:173)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:229)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:403)
at oracle.jdbc.driver.T4CStatement.doDescribe(T4CStatement.java:701)
at oracle.jdbc.driver.OracleStatement.getColumnIndex(OracleStatement.java:3355)
at oracle.jdbc.driver.OracleResultSetImpl.findColumn(OracleResultSetImpl.java:2009)
at oracle.jdbc.driver.OracleResultSet.getString(OracleResultSet.java:494)
at org.hibernate.type.StringType.get(StringType.java:18)
at org.hibernate.type.NullableType.nullSafeGet(NullableType.java:163)
at org.hibernate.type.NullableType.nullSafeGet(NullableType.java:154)
at org.hibernate.type.AbstractType.hydrate(AbstractType.java:81)
at org.hibernate.persister.entity.AbstractEntityPersister.hydrate(AbstractEntityPersister.java:2091)
at org.hibernate.loader.Loader.loadFromResultSet(Loader.java:1380)
at org.hibernate.loader.Loader.instanceNotYetLoaded(Loader.java:1308)
at org.hibernate.loader.Loader.getRow(Loader.java:1206)
at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:580)
at org.hibernate.loader.Loader.doQuery(Loader.java:701)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:236)
at org.hibernate.loader.Loader.doList(Loader.java:2217)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2108)
at org.hibernate.loader.Loader.list(Loader.java:2103)
at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:289)
at org.hibernate.impl.SessionImpl.listCustomQuery(SessionImpl.java:1696)
at org.hibernate.impl.AbstractSessionImpl.list(AbstractSessionImpl.java:142)
at org.hibernate.impl.SQLQueryImpl.list(SQLQueryImpl.java:152)
at org.springframework.orm.hibernate3.HibernateTemplate$34.doInHibernate(HibernateTemplate.java:1015)
at org.springframework.orm.hibernate3.HibernateTemplate$34.doInHibernate(HibernateTemplate.java:1)
at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:406) -
In my original email I should have made the point clear that an indexed
column was required, that led to some confusion, apologies.
Under Oracle 7 even if the column is indexed the query engine still does a
full scan of the index to find the maximum or minimum value. As strange as
this seems it is possible to view it using the Oracle trace functions such
as tkprof. This method is quicker than not having an index but the cursor
method is far more efficient.
When using a cursor based approach Oracle will go straight to the first
record of the index (depending on MAX or MIN) and retrieve the data. By
exiting at that point the function has been performed and the I/O operations
are extremely low compared to a full index scan.
Of course there is a trade off depending on the amount of rows but for large
indexed tables the cursor approach will be far faster than the normal
functions. I'm not sure how other RDBMS's handle MAX/MIN but this has been
my experience with Oracle. This process may be faster still by using PL/SQL
but then you are incorporating specific database languages which is
obviously a problem if you port to a different RDBMS. Here is some code you
can try for Oracle PL/SQL functions:
declare
cursor myCur1 is
select number_field
from number_table
order by number_field desc;
begin
open myCur1;
fetch myCur1 into :max_val;
close myCur1;
end;
I hope this clarifies things a bit more. If in doubt of the execution plan
of a performance critical query use the database trace functions as they
show up all sorts of surprises. MAX and MIN are easy to understand when
viewing code but perform poorly under Oracle, whether v8 behaves differently
I have yet to discover.
Cheers,
Dylan.
-----Original Message-----
From: [email protected] [mailto:[email protected]]
Sent: Thursday, 7 January 1999 3:37
To: [email protected]
Subject: RE: SQL functions in TOOL code
I guess my point is that MAX can always be implemented more
efficiently than the SORT/ORDER-BY approach (but may not be the
case, depending on the RDBMS). If an ORDER-BY
can use an index (which means that the indexing mechanism involves
a sorted collection rather than an unordered hashtable) so can
MAX - in which case finding a MAX value could be implemented
in either O(1) or O(logn) time, depending on the implementation.
The last sentence being the major point of this whole discussion,
which is that your mileage may vary depending on the RDBMS - so
try using both approaches if performance is a problem.
In terms of maintenance, MAX is the much more intuitive approach
(In My Opinion, of course), since a programmer can tell right away
what the code is attempting to do.
Chad Stansbury
BORN Information Services, Inc.
-----Original Message-----
From: [email protected]
To: [email protected]; [email protected]; [email protected]
Sent: 1/6/99 10:45 AM
Subject: RE: SQL functions in TOOL code
Well, yes, but in that specific case (looking for max() value) would not
be
true that, if you have an index (and only then) on that specific column
some
databases (like Oracle) will be smart enough to use index and find max
value
without full table scan and without using order by clause?
Dariusz Rakowicz
Consultant
BORN Information Services (http://www.born.com)
8101 E. Prentice Ave, Suite 310
Englewood, CO 80111
303-846-8273
[email protected]
-----Original Message-----
From: Sycamore [SMTP:[email protected]]
Sent: Wednesday, January 06, 1999 10:29 AM
To: [email protected]; [email protected]
Subject: Re: SQL functions in TOOL code
If (and only if) an index exists on the exact columns in the ORDER BY
clause, some databases are smart enough to traverse the index (inforward
or
reverse order) instead of doing a table scan followed by a sort.
If there is no appropriate index, you always end up with some kind ofsort
step.
Of course this is all highly schema- and database-dependent, so youmust
weigh those factors when deciding to exploit this behavior.
Kevin Klein
Sycamore Group, LLC
Milwaukee
-----Original Message-----
From: [email protected] <[email protected]>
To: [email protected] <[email protected]>
Date: Wednesday, January 06, 1999 9:40 AM
Subject: RE: SQL functions in TOOL code
This seems a bit counter-intuitive to me... primarily due to
the fact that both MAX and ORDER-BY functionality would require
a full table scan on the given column... no? However, I would
think that a MAX can be implemented more efficiently since it
just requires the max value in a given set (which can be performed
in O(n) time on an unordered set) versus an ORDER-BY (sort)
performance on an unordered set of at best O(nlogn) time.
Am I missing something? Please set me straight on this 'un.
Chad Stansbury
BORN Information Services, Inc.
-----Original Message-----
From: Jones, Dylan
To: 'Vuong, Van'
Cc: [email protected]
Sent: 1/5/99 4:42 PM
Subject: RE: SQL functions in TOOL code
Hi Van,
Operating a function such as MAX or MIN is possible as given in your
example
but it is worth pointing out the performance overhead with such a
method.
When you use MAX, Oracle will do a full table scan of the column so
if
you
have a great many rows it is very inefficient.
In this case use a cursor based approach and depending on your
requirments
(MAX/MIN) use a descending or ascending ORDER BY clause.
eg.
begin transaction
for ( aDate : SomeDateDomain ) in
sql select DATE_FIELD
from DATE_TABLE
order by
DATE_FIELD DESC
on session MySessionSO
do
found = TRUE;
aLatestDate.SetValue(aDate);
// Only bother about the first record
exit;
end for;
end transaction;
On very large tables the performance increases with the above method
will be
considerable so it is worth considering which method to use whensizing
your
database and writing your code.
Cheers,
Dylan.
-----Original Message-----
From: Vuong, Van [mailto:[email protected]]
Sent: Tuesday, 5 January 1999 6:50
To: [email protected]
Subject: SQL functions in TOOL code
Is it possible to execute a SQL function from TOOL code?
For example:
SQL SELECT Max(Version) INTO :MyVersion
FROM Template_Design
WHERE Template_Name = :TemplateName
ON SESSION MySession;
The function in this example is MAX().
I am connected to an Oracle database.
Thanks,
Van Vuong
To unsubscribe, email '[email protected]' with
'unsubscribe forte-users' as the body of the message.
Searchable thread archive<URL:http://pinehurst.sageit.com/listarchive/>
To unsubscribe, email '[email protected]' with
'unsubscribe forte-users' as the body of the message.
Searchable thread archive<URL:http://pinehurst.sageit.com/listarchive/>
>
To unsubscribe, email '[email protected]' with
'unsubscribe forte-users' as the body of the message.
Searchable thread archive<URL:http://pinehurst.sageit.com/listarchive/>
To unsubscribe, email '[email protected]' with
'unsubscribe forte-users' as the body of the message.
Searchable thread archive <URL:http://pinehurst.sageit.com/listarchive/>
To unsubscribe, email '[email protected]' with
'unsubscribe forte-users' as the body of the message.
Searchable thread archive <URL:http://pinehurst.sageit.com/listarchive/>
To unsubscribe, email '[email protected]' with
'unsubscribe forte-users' as the body of the message.
Searchable thread archive <URL:http://pinehurst.sageit.com/listarchive/> -
Displaying errors when Enable automatic error handling option is on
In order to display error messages do I need general or simple error handler to implement if I have Enable automatic error handling on?
Solved!
Go to Solution.Both will (optionally) display a popup when an error occurs. The general error handler just has more options for special cases. The simple error handler is typically sufficient.
If you havce automatic error handing enabled, you'll get a popup whenever a function generates an error AND the error output is not wired. Once you wire an error handler, the automatic error handling will no longer occur.
To display an error, you can also just place a plain error indicator on the front panel. This avoids annoying popup messages.
LabVIEW Champion . Do more with less code and in less time . -
Execution properties, Enable automatic error handling
Hi
I am writing real-time code for standalone execution on a cRIO-9074.
If I untick the "Enable automatic error handling" option in VI properties (Execution), what is the consequence if I have an application with no error handling case structures to detect the occurrence of errors elsewhere and within subVI's ? Does the error just go undetected and the application continue regardless? If ticked, could a standalone application hang as there is no user-interface for the error to get reported automatically to? Can I configure the LabVIEW RTE to automatically handle errors in a certain way regardless of individual VI settings of the "Enable automatic error handling" option?
I am a bit confused by the usefulness of "Enable automatic error handling" within RT/FPGA code, and where in the development process it is best enabled then disabled (if necessary).
ThanksIf I untick the "Enable automatic error handling" option in VI properties (Execution), what is the consequence if I have an application with no error handling case structures to detect the occurrence of errors elsewhere and within subVI's ? Does the error just go undetected and the application continue regardless?
That's the case: the error is lost (i.e. it's not handled), and the application goes on.
If ticked, could a standalone application hang as there is no user-interface for the error to get reported automatically to?
The property "Enable automatic error handling" is not availabe in the run-time engine, so there's no automatic error handling in a built application,
Can I configure the LabVIEW RTE to automatically handle errors in a certain way regardless of individual VI settings of the "Enable automatic error handling" option?
No, for the reason stated above.
I am a bit confused by the usefulness of "Enable automatic error handling" within RT/FPGA code, and where in the development process it is best enabled then disabled (if necessary).
There's no "Enable automatic error handling" property in Labview RT either.
Regards,
Marco -
'Call' in PL/SQL button event handler
I have created a form with only one 'Custom' button on it.
In the PL/SQL button event handler, in 'Custom' event item, I
inserted some PL/SQL code and, at the end, a call like the
following:
my_url:= 'PORTAL30.wwv_component_control.run_as_portlet?'
|| 'p_module_id=' || '2836550185';
call(my_url,return_url);
I have a compilation error:
"PLS-00201: identifier 'CALL' must be declared"
I also tried to put this code in 'On successful submission of a
form'. I have no compilation error but it doesn't work.
Anybody knows hw to solve this problem?
Thanks.Hello Antonnella,
I have a good tip for you:
write the next scirp in the 'On successful submission of a
form'field in the form where you want to call the component:
declare
l_url varchar2(2000);
begin
l_url := 'the url of the component you want to call' ;
PORTAL30.wwa_app_module.set_target(l_url,'CALL');
end;
you can get the url from:
develop -> call interface:show -> Example of Call from URL .
Success,
Haseeb -
Hello All,
I am supporting a Java 5 project on Tomcat. We've used Spring and Stored Procedure in the project.
Recently we deployed our application in a GoLive environment and have started seeing Timeout errors in log files. After around two days we also have to restart Tomcat as users are no more able to login to access the application.
Same application runs fine without any timeout issues on another environment.
The only difference between two environments is that the Go-Live env has a firewall between Tomcat and Database and the other environment hosts both Tomcat and Database on same machine (i.e. no firewall).
For GoLive env the only port open on firewall for JDBC connection is 1521 and is used in the connection string url for obtaining the connections.
When there is a Timeout error, the N/w admin guy observed that the JDBC connection was not attempted on 1521 port, but on some random port which is not open on firewall, due to which the Database server logs also do not show entry for this connection attempt as it gets blocked by the firewall.
I am not sure why a randam port should be used to connect when a specific port is mentioned in the connection url? Also what can be making this port switching?
Application uses Apache DBCP with Spring to obtain connections.
Has anyone experienced similar errors?
Any suggestions/help on this issue is greatly appreciated!
Many Thanks,
CD
===============================
Error Log Extract:
Error while extracting database product name - falling back to empty error codes
org.springframework.jdbc.support.MetaDataAccessException: Error while extracting DatabaseMetaData; nested exception is java.sql.SQLException: Closed Connection
java.sql.SQLException: Closed Connection
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:146)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:208)
at oracle.jdbc.driver.PhysicalConnection.getMetaData(PhysicalConnection.java:1605)
at org.apache.commons.dbcp.DelegatingConnection.getMetaData(DelegatingConnection.java:247)
at org.apache.commons.dbcp.DelegatingConnection.getMetaData(DelegatingConnection.java:247)
at org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.getMetaData(PoolingDataSource.java:231)
at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:172)
at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:207)
at org.springframework.jdbc.support.SQLErrorCodesFactory.getErrorCodes(SQLErrorCodesFactory.java:187)
at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.setDataSource(SQLErrorCodeSQLExceptionTranslator.java:126)
at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.<init>(SQLErrorCodeSQLExceptionTranslator.java:92)
at org.springframework.jdbc.support.JdbcAccessor.getExceptionTranslator(JdbcAccessor.java:96)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:294)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:348)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:352)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:356)
at com.o2.morse.dao.impl.sql.UserDaoImpl.batchLoad(UserDaoImpl.java:371)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:287)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:181)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:148)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:170)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:176)
at $Proxy3.batchLoad(Unknown Source)
at com.o2.morse.domain.User.doHousekeeping(User.java:667)
at com.o2.morse.domain.User$$FastClassByCGLIB$$372ff70b.invoke(<generated>)
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:149)
at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:705)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:148)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:170)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:643)
at com.o2.morse.domain.User$$EnhancerByCGLIB$$d5ac966a.doHousekeeping(<generated>)
at com.o2.morse.scheduler.EndOfDay.run(EndOfDay.java:63)
at com.o2.morse.scheduler.EndOfDay$$FastClassByCGLIB$$3b2d4927.invoke(<generated>)
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:149)
at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:705)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:148)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:170)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:643)
at com.o2.morse.scheduler.EndOfDay$$EnhancerByCGLIB$$488a9f86.run(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.springframework.util.MethodInvoker.invoke(MethodInvoker.java:248)
at org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean$MethodInvokingJob.executeInternal(MethodInvokingJobDetailFactoryBean.java:165)
at org.springframework.scheduling.quartz.QuartzJobBean.execute(QuartzJobBean.java:90)
at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:525)
Could not close JDBC Connection
java.sql.SQLException: Already closed.
at org.apache.commons.dbcp.PoolableConnection.close(PoolableConnection.java:77)
at org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.close(PoolingDataSource.java:180)
at org.springframework.jdbc.datasource.DataSourceUtils.doReleaseConnection(DataSourceUtils.java:286)
at org.springframework.jdbc.datasource.DataSourceUtils.releaseConnection(DataSourceUtils.java:247)
at org.springframework.jdbc.datasource.DataSourceTransactionManager.doCleanupAfterCompletion(DataSourceTransactionManager.java:297)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.cleanupAfterCompletion(AbstractPlatformTransactionManager.java:754)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollback(AbstractPlatformTransactionManager.java:615)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.rollback(AbstractPlatformTransactionManager.java:560)
at org.springframework.transaction.interceptor.TransactionAspectSupport.doCloseTransactionAfterThrowing(TransactionAspectSupport.java:284)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:100)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:170)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:176)
at $Proxy3.batchLoad(Unknown Source)
at com.o2.morse.domain.User.doHousekeeping(User.java:667)
at com.o2.morse.domain.User$$FastClassByCGLIB$$372ff70b.invoke(<generated>)
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:149)
at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:705)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:148)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:170)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:643)
at com.o2.morse.domain.User$$EnhancerByCGLIB$$d5ac966a.doHousekeeping(<generated>)
at com.o2.morse.scheduler.EndOfDay.run(EndOfDay.java:63)
at com.o2.morse.scheduler.EndOfDay$$FastClassByCGLIB$$3b2d4927.invoke(<generated>)
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:149)
at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:705)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:148)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:170)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:643)
at com.o2.morse.scheduler.EndOfDay$$EnhancerByCGLIB$$488a9f86.run(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.springframework.util.MethodInvoker.invoke(MethodInvoker.java:248)
at org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean$MethodInvokingJob.executeInternal(MethodInvokingJobDetailFactoryBean.java:165)
at org.springframework.scheduling.quartz.QuartzJobBean.execute(QuartzJobBean.java:90)
at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:525)
Application exception overridden by rollback exception
org.springframework.jdbc.UncategorizedSQLException: StatementCallback; uncategorized SQLException for SQL [SELECT ID_USER_DETAILS, USERNAME, CREATED_ON, LAST_LOGIN FROM USER_DETAILS WHERE STATUS = 157 AND SUPERUSER <> 'Y']; SQL state [null]; error code [17002] ; Io exception: Connection timed out; nested exception is java.sql.SQLException: Io exception: Connection timed out
java.sql.SQLException: Io exception: Connection timed out
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:146)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:255)
at oracle.jdbc.driver.T4CStatement.executeForDescribe(T4CStatement.java:820)
at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:1049)
at oracle.jdbc.driver.T4CStatement.executeMaybeDescribe(T4CStatement.java:845)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1154)
at oracle.jdbc.driver.OracleStatement.executeQuery(OracleStatement.java:1313)
at org.apache.commons.dbcp.DelegatingStatement.executeQuery(DelegatingStatement.java:205)
at org.apache.commons.dbcp.DelegatingStatement.executeQuery(DelegatingStatement.java:205)
at org.springframework.jdbc.core.JdbcTemplate$1QueryStatementCallback.doInStatement(JdbcTemplate.java:333)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:282)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:348)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:352)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:356)
at com.o2.morse.dao.impl.sql.UserDaoImpl.batchLoad(UserDaoImpl.java:371)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:287)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:181)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:148)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:170)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:176)
at $Proxy3.batchLoad(Unknown Source)
at com.o2.morse.domain.User.doHousekeeping(User.java:667)
at com.o2.morse.domain.User$$FastClassByCGLIB$$372ff70b.invoke(<generated>)
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:149)
at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:705)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:148)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:170)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:643)
at com.o2.morse.domain.User$$EnhancerByCGLIB$$d5ac966a.doHousekeeping(<generated>)
at com.o2.morse.scheduler.EndOfDay.run(EndOfDay.java:63)
at com.o2.morse.scheduler.EndOfDay$$FastClassByCGLIB$$3b2d4927.invoke(<generated>)
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:149)
at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:705)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:148)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:170)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:643)
at com.o2.morse.scheduler.EndOfDay$$EnhancerByCGLIB$$488a9f86.run(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.springframework.util.MethodInvoker.invoke(MethodInvoker.java:248)
at org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean$MethodInvokingJob.executeInternal(MethodInvokingJobDetailFactoryBean.java:165)
at org.springframework.scheduling.quartz.QuartzJobBean.execute(QuartzJobBean.java:90)
at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:525)
Batch Job Failed: org.springframework.transaction.TransactionSystemException: Could not roll back JDBC transaction; nested exception is java.sql.SQLException: Closed ConnectionI am using latest Jrockit 16)5, ojdbc6_g.jar,spring.jar Weblogic 10.3 and Oracle 10G 10.2.4 .. whatever but always get "Closed Connection"
java.lang.Throwable: Closed Connection
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:146)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:208)
at oracle.jdbc.driver.PhysicalConnection.createStatement(PhysicalConnection.java:750)
at oracle.jdbc.OracleConnectionWrapper.createStatement(OracleConnectionWrapper.java:183)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:27)
at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:7053)
at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:121)
at weblogic.servlet.internal.WebAppServletContext.invokeServlet(WebAppServletContext.java:3902)
at weblogic.servlet.internal.ServletRequestImpl.execute(ServletRequestImpl.java:2773)
at weblogic.kernel.ExecuteThread.execute(ExecuteThread.java:224)
at weblogic.kernel.ExecuteThread.run(ExecuteThread.java:183) -
[LV 7.1 Pro on WinXP for Tablet PC's]
I recently let a rather large LV app of mine run in the development environment while I was out for a couple of days. Upon returning I found that the app had hung for ~22 hours waiting for an answer to an Automatic Error Handling (AEH) dialog proclaiming an Error 7 in New File without any indication of the VI hierarchy that called New File. I set about ensuring that AEH dialogs would not pop up and have not been able to discover how I could have possibly received one in the first place.
Subsequent investigation revealed:
Neither AEH option in Options>Block Diagrams were checked.
Network problems had occurred around the time that the app had hung. All file paths are network paths when running in the development environment, so the cause of the error was most likely valid, even if the AEH dialog appearance wasn't.
My app has only one instance where the New File primitive is used by me. That subVI and all others above it in the hierarchy DO NOT have the AEH property enabled. The error out cluster of New File in my subvi is wired.
My app has three instances where New File is called from a vi.lib vi (Open/Create/Replace File.vi, Open Config Data.vi, and Prompt Web Browser Path.vi), none of which have the AEH property enabled. Nor does any of their calling VI's. All three instances also have their error out cluster wired.
A utility to examine the AEH property of all VI's (with all top level and dynamic VI's loaded) in memory reported that only 1 of 308 vi's ( RGT Does File Exists.vi from the Report Generation Toolkit) had that property true. That vi has no subVI's other than the File/Directory Info primitive and no calling VI's in common with any of the vi's that call New File, except a top level VI.
As long as 'Enable automatic error handling dialogs' remains unselected in options>block diagram, I am unable to get an AEH dialog for either the New File or File/Directory Info primitives in a test VI with AEH property enabled and their error out clusters unwired no matter what invalid path I pass to the functions. As soon as the options>block diagram>Enable AEH dialogs' is selected, both primitives fire AEH dialogs with no error out wired and don't when wired. i.e. works as advertised.
In other words I can find no reason why I should have gotten the problem AEH dialog...
I cannot afford for this app to hang because of a network problem, other portions of the app that were running concurrently correctly handled the error and, had the AEH dialog not appeared, the app would have made corrections or shutdown in an orderly fashion.
Any ideas?Very good.
Write Characters to File.vi>Open/Create/Replace File.vi>New File
New File throws the error. Open/Create/Replace strips the hierarchy from the source of the error. Write Characters passes it to the General Error Handler. I never looked above O/C/R file in the hierarchy except for enable automatic error handling property. The tip-off should have been to realize that O/C/R file was stripping the hierarchy from the error and look above that.
The real irony is that Write Characters was being used to log error cluster data to an error log file...
Save as... Copy without updating... the OEM 'Write Characters to File' is gone from this app.
Thanx (a bunch) -
How to get a form field valud in delete PL/SQL Button Event Handler
Hi Friend,
I have a form. when user clicks delete button. we want to remove system dodelete function
and add a delete script
Under delete-top category,
how can I get value of form EVENT_NUMBER field in form at delete PL/SQL Button Event Handler?
DELETE FROM PTEAPP.PTE_EVENTS WHERE eventnumber = EVENT_number
But when I try to save this form and get message as
1721/15 PLS-00201: identifier 'EVENT_NUMBER' must be declared
Thanks for any help!
newuserI did something similar but wasn't using a stored procedure. Couldn't you set a flag variable once you know you're not doing the insert and in the "before displaying the form" section put an IF to check if your flag was set, and if so do an HTP.Print('You are overpaid buddy!');
Then just reset your flag. -
Is there a way to automate the tax code assignation on non PO documents lik
I'm looking for a way to automate the tax code assignation on purchases, I'm aware of the condition techniques for POs, but I would like to understand if it can be also applied to the other document in purchases so we can have a totally automate process on tax code assignation.
Documents like: Contracts, Info records, RFQ, Scheduling agreements, Outline AgremmentsWhat you need to do is to create condition tables & access sequences for condition type NAVS for purchasing documents like RFQ, Contract & Scheduling agreement. You can use the document types and document category to differentiate these. Obviously this is required only if your tax determination scenario is different between different document type, if the tax code to be determined is not linked to purchasing document type, then you only one access sequence which can have parameteris like PORG, vendor if required etc. which are common to all document types.
Once this configuration is done, then you need to maintain condition records using transaction MEK1 and maintain the tax codes as per the combination of parameters.
In case of Info-record, it is different as it is a master data and this automatic tax determination will not work there. -
It takes long time to invoke the Exception handler code
In our setup there is firewall between the Appserver that is using toplink and the database.The firewall terminates idle connection on any port if the connection is idle for 1 hr.So i have implemented an exception handler to reconnect when the connection is broken.The code works fine but It takes 15 mins for the exception handler code to be invoked.
The database is Oracle and the driver is thin driver,OS is solaris.No external connection pool
I had registered the exceptionhandler to the serversession,should i register it with each ClientSession?yes ,15 mins is the time taken before the server session's exception handler code is invoked.
The following is the exception handler code on the sever session.Any thing wrong?
server.setExceptionHandler(new ExceptionHandler()
public Object handleException(RuntimeException ex)
{//This method is executed only after 15 min ,if the connection is broken
String mess=ex.getMessage();
System.out.println("In handler excep mess is "+mess);
if ((ex instanceof DatabaseException) && (mess.equals("connection reset by peer.")||(mess.indexOf("IOException :Broken pipe")!=-1)))
DatabaseException dbex = (DatabaseException) ex;
dbex.getAccessor().reestablishConnection (dbex.getSession());
return dbex.getSession().executeQuery(dbex.getQuery());
return null;
What could be wrong ?
I tried Oracle's connection cache Impl created a connection pool using the same thin driver and on the same env.SQLException is thrown immediately on using the broken connection.so I feel the driver is not causing any problem.
Is there any way in toplink to keep the connections active?or Is there any way to poll all connections in the connection pool and check If they are connected instead of waiting until the exception gets thrown and handle it?
Maybe you are looking for
-
How to change primary keys of existing InfoCube.
Greetings everyone! Im trying to change the Key Fields in my reporting architecture as per our new company mandate. Ive been able to successfully change the primary keys for DS, DSO and InfoSource. Can any kind soul out there please tell me how t
-
'Options..' button in Airport Preference Pane doesn't work.
While in the Network preference pane located within your System Preferences, if you double-click on Airport while in the Network Status view, there is a 'Options...' button at the bottom of the screen. For a while now, after clicking on this button,
-
Keep getting message saying current version of Safari does not support gmail, but I seem to have latest version (5.0.5). Is there an update I need? Poroblem goes away when I use Chrome.
-
Can you replace existing images in Captivate 7 the way you can when using InDesign?
Can you replace existing images in Captivate 7 the way you can when using InDesign? I need to replace some images but wondering if I'll need to reformat, resize, rename for the Advanced Action, etc.
-
I wanted to download a video off of youtube but the button for downloading doesn't appear where it usually is. I tried refreshing the page and I tried other videos as well, but the "download" button doesn't show up. Anyone else experiencing this?