SQL requests when handling a refresh on a persistent-dirty instance
I just noticed that Kodo issues two SQL requests when handling a refresh
on a persistent-dirty instance, the first one getting the JDOLOCKX
column value.
For a persistent-clean instance, it makes sense to get the version
number first and to check if it has been changed. If not, the attribute
values are not read from the database.
For a persistent-dirty instance, as the memory state has been changed,
it has to be reloaded anyway and it seems to me that the first request
is useless.
Any confirmation ?
Thanks.
Yeah, the version check seems to be extraneous. We'll see what we can do
about that. Thanks for pointing it out!
Similar Messages
-
Why are cookies not updated in the request when meta refresh is used?
I've written a web site that uses IIS Forms Authentication. It's configured to use authentication tickets with a sliding expiration. FireFox allows the ticket to expire while it works fine with Internet Explorer.
The web site uses a Keep Alive page that uses the meta refresh tag to periodically post back to the server to keep authenticated. This is done because some users have a need to use another web site that does not run in IIS and we don't want their authentication to time out while they are there.
I used Fiddler to monitor the requests and responses and found that when IIS sends the updated cookie with the authentication ticket containing the revised expiration date, the cookie appears to be accepted by FireFox (according to CookieSafe as recorded in the error console Ctrl-shift-J). When the meta refresh occurs, the browser sends the original request with the obsolete cookie. This keeps occurring until the expiration time is up on the ticket. IIS keeps sending new cookies but they seem to be ignored. IE, on the other hand, accepts the cookie and you see it in the next request for the keep alive page.
I figure it might be related to caching, but I think I disabled that and it still does it. I'm going to try adding a random code to the KeepAlive url but I can't see why that should matter. Why wouldn't FireFox send the cookies as the values are set? I'm hoping this can be fixed with a simple config change.I was able to figure out what the problem was. The initial authentication cookie had a blank cookie domain while the new cookies that IIS would try to reissue had a domain name. IE doesn't seem to care but FireFox did. FireFox should have logged an error but instead said it was accepted.
My app works as it's supposed to now. -
Password request when refreshing pofcasts
Getting the following message when Podcasts are refreshing
To Access this site you need to log into area "idisk.mac.com" on web.mac.com
It requires you to enter a User Name and password, none of my passwords work. I have never seen this before.Problem solved.
One of the Podcasts was a non public Podcast that had a password attached. For some reason it lost its keychain (probably due to a reset of Safari) and was asking for a password. The only way to fix it was to re-subscribe via the WEB site and reestablish the keychain. -
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 -
Invalid month sql request for chart
Hi,
i try to refresh a report with a dynamical sql request as following :
select NULL LINK, status_label LABEL, count(fcr.status_code) as VALUE
from table
where table.date > '05/06/2007'
This query is generated dynamicaly from a date picker.
My problem is that the chart witch should be refreshed by this query, isn't.
The following error message come from the ajax query :
chart Flash Chart error: ORA-20987: APEX - Flash Chart error: - ORA-20001: Fetch error: ORA-01843: not a valid month
Something disapoint me: when i execute the query in plSQL i have got my wished results.
Does someone have any idea about this mistake?Hi better,
Try to give
where table.date >to_date( '05/06/2007','dd/mm/yyyy');Brgds,
Mini
Mark Answers Promptly -
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. -
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. -
Unable to view SQL Request in Log files
Hi Folks,
I am facing an issue which I am unable to find out the solution to view the physical query generated in log files in Presentation Services.
Below is the SQL Request generated but I want to view the exact physical query i.e SQL Request which is hitting DB.
So please guiude me to resolve this issue, I guess it is because of Initialization blocks created which is blocking to view the SQL request.
-------------------- SQL Request:
set variable LOGLEVEL = 7;SELECT "- Policy Effective-Start Date"."Start Quarter" saw_0, "- Insurance Policy Facts".Revenue saw_1, "- Insurance Policy Facts"."# Insurance Policies" saw_2, "Insurance Policy".Status saw_3, "Insurance Policy".Type saw_4 FROM "Insurance Policies" WHERE ("Insurance Policy".Type = 'Policy') AND ("- Policy Effective-Start Date"."Start Julian Day Number" BETWEEN VALUEOF(CURRENT_JULIAN_DAY)-365 AND VALUEOF("CURRENT_JULIAN_DAY")) ORDER BY saw_0, saw_3, saw_4
/* QUERY_SRC_CD='rawSQL' */
Regards
DjThere is no Enterprise Edition of SSMS. There is SSMS Basic and SSMS Complete. Prior to 2012 sp1, only SSMS Basic were available with Express Edition - but as of 2012 sp1 Expredd also offers SSMS Complete. SSMS Complete is selected bu default when you install
SSMS (unless you are prior to 2012 sp1 and are using Express, of course).
However, even SSMS Basic *should* show Agent assuming you have permissions for that. This is hearsay, but from trusted sources. Here is what to do:
Check what is installed for the machine from where you are running SSMS. You can do that using SQL Server Installation Center - see this blog post: http://sqlblog.com/blogs/tibor_karaszi/archive/2011/02/10/what-does-this-express-edition-look-like-anyhow.aspx
(towards the end).
On that machine try both this problematic account as well as an account which is sysadmin. Does the sysadmin account see Agent? If so, you know permissions aren't granted properly. If not, then you know the tool is the problme.
Also try the problematic account from a machine where you know you see Agent normally. Again, this will help you assess whether the problem is the tool (SSMS) or permissions for the account.
Tibor Karaszi, SQL Server MVP |
web | blog -
Error 1064 An exception occurred in the service when handling the control
Hi all,
I downloaded Oracle Business Intelligence 10.1.3.4.1 on windows XP successfully, once I try to start any service of Oracle BI [scheduler/server]. This error is shown *1064 An exception occurred in the service when handling the control request*.
Could anyone help me out?
Thanks in advance
MaithaI checked the file
[68008] Scheduler Error: [nQSError: 67042] The Scheduler Configuration is incorrect.
[nQSError: 67004] Registry value for SchedulerScriptPath not set.
How the issue can be resolved ? -
Execute procedure in pl/sql button event handler
i have a demo application which consists of text boxes
eg : when i enter department no in first text box and click proc
it should display dname and loc in the below text boxes.
my proc is working fine in sql*plus but its showing errors in pl/sql button event handler.
any ideas
my proc is create or replace procedure proc1 (no number)
as
DNAME1 dept.dname%type;
LOC1 dept.loc%type;
begin
select DNAME,LOC into DNAME1,LOC1 from scott.dept where deptno = no;
DBMS_OUTPUT.PUT_LINE (DNAME1);
DBMS_OUTPUT.PUT_LINE (LOC1);
Exception When No_Data_Found then
dbms_output.put_line('Entred name is not found');
When Others then
Null;
End;
/Hi,
you have to use
htp.p('<SCRIPT LANGUAGE="Javascript1.1">
document.all("FORMNAME.DEFAULT.ATTRIBUTENAME.01").value="'||DNAME1||'";
document.all("FORMNAME.DEFAULT.ATTRIBUTENAME.01").value="'||LOC1||'";
</SCRIPT>
instead of
DBMS_OUTPUT.PUT_LINE (DNAME1);
DBMS_OUTPUT.PUT_LINE (LOC1);
where formname is your form name and attribute name is the field name on the page. -
Help asked for a sql request - thanks
Hello,
I'm not a sql Guru... Who can help for this sql request ?
First I have this:
SELECT ADDINFO_ID, INFO, LANGUAGE_FK, ENGLISH_NAME
FROM V_ADDINFOS
WHERE LANGUAGE_FK = 'EN' (which is very simple...-)
But now complicated... I have to add this in the same request:
select sum(val) as nbrInfo
from(
select count(*) val from eccgis where addinfo1_fk = ADDINFO_ID
union all
select count(*) val from eccgis where addinfo2_fk = ADDINFO_ID
union all
select count(*) val from eccgis where addinfo3_fk = ADDINFO_ID
union all
select count(*) val from thirdgis where addinfo1_fk = ADDINFO_ID
union all
select count(*) val from thirdgis where addinfo2_fk = ADDINFO_ID
In other words, for each row of the first select, I need to know how much it is linked in the tables eccgis and thirdgis...
Hope is is clear... -)
Thank you very very much,
MichelHi, Michel,
Almost anywhere that SQL allows an expression (such as a column name, literal or function call) it also allows a scalar sub-query, a SELECT statement based on any table (or tables) that returns one column and (at most) one row. Like other sub-queries, scalar sub-queries can be corellated to the main query.
To get the grand total you want on each row of your output:
SELECT ADDINFO_ID, INFO, LANGUAGE_FK, ENGLISH_NAME
, (select count(*) from eccgis where addinfo1_fk = ADDINFO_ID)
+ (select count(*) from eccgis where addinfo2_fk = ADDINFO_ID)
+ (select count(*) from eccgis where addinfo3_fk = ADDINFO_ID)
+ (select count(*) from thirdgis where addinfo1_fk = ADDINFO_ID)
+ (select count(*) from thirdgis where addinfo2_fk = ADDINFO_ID)
AS nrbInfo
FROM V_ADDINFOS
WHERE LANGUAGE_FK = 'EN';VERY IMPORTANT: Each sub-query must be in parentheses. You'll get a run-time error if any scalar sub-query returns more than one row. (Returning no rows is okay: the value will be NULL).
By the way, this looks like a bad table design. If each row in eccgis or thirdgis can be associated with more than one foreign key, they should be kept in a separate table. That's the standard way to handle many-to-many relationships. -
How to avoid updating the data when ever we refresh the page
I want to avoid updating the data to the server when ever we refresh the web page.
Thanks in advance.You could potentially do it by using a redirect instead of a forward to the result page.
That will essentially do it in two requests. 1 to request the save, another to display the result of the save.
If the user then requests a refresh, it won't incur a save call.
Of course, that doesn't stop them going back in the browser, and refreshing that page, but it at least makes it a little harder.
Cheers,
evnafets -
Which form will be submitted when i click refresh button.
HI,
which form will be submitted when i click on refresh button.When you click refresh button, it will send to the server the exact same request that it sent to get to the current page.
If the previous navigation was done by a form submission, then yes, that form submission will be repeated. -
Tools for Anaylsing DB request when loading a cube
Hello everyone !
I have seen in documentation a screen in BW where you can see, while a cube is loading, usefull informations about SQL statement (request code, elapsed time...).
(It is may be accessible from SM50 while prosseces are running).
Anyone has got idea about this management tools (transaction name) ?
Thanks
Best Regards
FredIt's much like ST05 !
When I load a cube, I have for instance an update routine for the infoobjet XXX.
Is it possible to get, for the whole datapackage, the time elapsed for this particular sql statement ?
Thanks anyway,
Best Regards
Fred -
Performance issue on 1 SQL request
Hi,
We have a performance problem. We have 2 systems. PRD and QAS (QAS is a copy of PRD as of September 2nd)
SQL request is identical.
table structures is identical.
indexes are identical.
views are identical
DB stats have all been recalculated on both systems
initSID.ora values are almost identical. only memory related parameters (and SID) are different.
Obviously, data is different
For you info, view ZBW_VIEW_EKPO fetched its info from tables EIKP, LFA1, EKKO and EKPO.
Starting on September 15th, a query that used to take 10 minutes started taking over 120 minutes.
I compared explain plans on both system and they are really different:
SQL request:
SELECT
"MANDT" , "EBELN" , "EBELP" , "SAISO" , "SAISJ" , "AEDAT" , "AUREL" , "LOEKZ" , "INCO2" ,
"ZZTRANSPORT" , "PRODA" , "ZZPRDHA" , "ZZMEM_DATE" , "KDATE" , "ZZHERKL" , "KNUMV" , "KTOKK"
FROM
"ZBW_VIEW_EKPO"
WHERE
"MANDT" = :A0#
Explain plan for PRD:
SELECT STATEMENT ( Estimated Costs = 300,452 , Estimated #Rows = 0 )
8 HASH JOIN
( Estim. Costs = 300,451 , Estim. #Rows = 4,592,525 )
Estim. CPU-Costs = 9,619,870,571 Estim. IO-Costs = 299,921
Access Predicates
1 TABLE ACCESS FULL EIKP
( Estim. Costs = 353 , Estim. #Rows = 54,830 )
Estim. CPU-Costs = 49,504,995 Estim. IO-Costs = 350
Filter Predicates
7 HASH JOIN
( Estim. Costs = 300,072 , Estim. #Rows = 4,592,525 )
Estim. CPU-Costs = 9,093,820,218 Estim. IO-Costs = 299,571
Access Predicates
2 TABLE ACCESS FULL LFA1
( Estim. Costs = 63 , Estim. #Rows = 812 )
Estim. CPU-Costs = 7,478,316 Estim. IO-Costs = 63
Filter Predicates
6 HASH JOIN
( Estim. Costs = 299,983 , Estim. #Rows = 4,592,525 )
Estim. CPU-Costs = 8,617,899,244 Estim. IO-Costs = 299,508
Access Predicates
3 TABLE ACCESS FULL EKKO
( Estim. Costs = 2,209 , Estim. #Rows = 271,200 )
Estim. CPU-Costs = 561,938,609 Estim. IO-Costs = 2,178
Filter Predicates
5 TABLE ACCESS BY INDEX ROWID EKPO
( Estim. Costs = 290,522 , Estim. #Rows = 4,592,525 )
Estim. CPU-Costs = 6,913,020,784 Estim. IO-Costs = 290,141
4 INDEX SKIP SCAN EKPO~Z02
( Estim. Costs = 5,144 , Estim. #Rows = 4,592,525 )
Search Columns: 2
Estim. CPU-Costs = 789,224,817 Estim. IO-Costs = 5,101
Access Predicates Filter Predicates
Explain plan for QAS:
SELECT STATEMENT ( Estimated Costs = 263,249 , Estimated #Rows = 13,842,540 )
7 HASH JOIN
( Estim. Costs = 263,249 , Estim. #Rows = 13,842,540 )
Estim. CPU-Costs = 59,041,893,935 Estim. IO-Costs = 260,190
Access Predicates
1 TABLE ACCESS FULL LFA1
( Estim. Costs = 63 , Estim. #Rows = 812 )
Estim. CPU-Costs = 7,478,316 Estim. IO-Costs = 63
Filter Predicates
6 HASH JOIN
( Estim. Costs = 263,113 , Estim. #Rows = 13,842,540 )
Estim. CPU-Costs = 57,640,387,953 Estim. IO-Costs = 260,127
Access Predicates
4 HASH JOIN
( Estim. Costs = 2,127 , Estim. #Rows = 194,660 )
Estim. CPU-Costs = 513,706,489 Estim. IO-Costs = 2,100
Access Predicates
2 TABLE ACCESS FULL EIKP
( Estim. Costs = 351 , Estim. #Rows = 54,830 )
Estim. CPU-Costs = 49,504,995 Estim. IO-Costs = 348
Filter Predicates
3 TABLE ACCESS FULL EKKO
( Estim. Costs = 1,534 , Estim. #Rows = 194,660 )
Estim. CPU-Costs = 401,526,622 Estim. IO-Costs = 1,513
Filter Predicates
5 TABLE ACCESS FULL EKPO
( Estim. Costs = 255,339 , Estim. #Rows = 3,631,800 )
Estim. CPU-Costs = 55,204,047,516 Estim. IO-Costs = 252,479
Filter Predicates
One more bit of information, PRD was copied to TST about a month ago and this one is also slow.
I did almost anything I could think of.> DB stats have all been recalculated on both systems
> initSID.ora values are almost identical. only memory related parameters (and SID) are different.
> Obviously, data is different
Ok, so you say: the parameters are different, the data is different and the statistics are different.
I'm surprised that you still expect the plans to be the same...
> For you info, view ZBW_VIEW_EKPO fetched its info from tables EIKP, LFA1, EKKO and EKPO.
We will need to see the view definition !
> Starting on September 15th, a query that used to take 10 minutes started taking over 120 minutes.
Oh - Sep. 15th - that explains it ... just kiddin'.
Ok, so it appears to be obvious that from that day on, the execution plan for the query was changed.
If you're on Oracle 10g you may look it up again and also recall the CBO stats that had been used back then.
> I compared explain plans on both system and they are really different:
>
> SQL request:
>
SELECT
> "MANDT" , "EBELN" , "EBELP" , "SAISO" , "SAISJ" , "AEDAT" , "AUREL" , "LOEKZ" , "INCO2" ,
> "ZZTRANSPORT" , "PRODA" , "ZZPRDHA" , "ZZMEM_DATE" , "KDATE" , "ZZHERKL" , "KNUMV" , "KTOKK"
> FROM
> "ZBW_VIEW_EKPO"
> WHERE
> "MANDT" = :A0#
Ok - basically you fetch all rows from this view as MANDT is usually not a selection criteria at all.
> Explain plan for PRD:
>
SELECT STATEMENT ( Estimated Costs = 300,452 , Estimated #Rows = 0 )
>
> 8 HASH JOIN
> ( Estim. Costs = 300,451 , Estim. #Rows = 4,592,525 )
> Estim. CPU-Costs = 9,619,870,571 Estim. IO-Costs = 299,921
> Access Predicates
>
> 1 TABLE ACCESS FULL EIKP
> ( Estim. Costs = 353 , Estim. #Rows = 54,830 )
> Estim. CPU-Costs = 49,504,995 Estim. IO-Costs = 350
> Filter Predicates
> 7 HASH JOIN
> ( Estim. Costs = 300,072 , Estim. #Rows = 4,592,525 )
> Estim. CPU-Costs = 9,093,820,218 Estim. IO-Costs = 299,571
> Access Predicates
>
> 2 TABLE ACCESS FULL LFA1
> ( Estim. Costs = 63 , Estim. #Rows = 812 )
> Estim. CPU-Costs = 7,478,316 Estim. IO-Costs = 63
> Filter Predicates
> 6 HASH JOIN
> ( Estim. Costs = 299,983 , Estim. #Rows = 4,592,525 )
> Estim. CPU-Costs = 8,617,899,244 Estim. IO-Costs = 299,508
> Access Predicates
>
> 3 TABLE ACCESS FULL EKKO
> ( Estim. Costs = 2,209 , Estim. #Rows = 271,200 )
> Estim. CPU-Costs = 561,938,609 Estim. IO-Costs = 2,178
> Filter Predicates
> 5 TABLE ACCESS BY INDEX ROWID EKPO
> ( Estim. Costs = 290,522 , Estim. #Rows = 4,592,525 )
> Estim. CPU-Costs = 6,913,020,784 Estim. IO-Costs = 290,141
>
> 4 INDEX SKIP SCAN EKPO~Z02
> ( Estim. Costs = 5,144 , Estim. #Rows = 4,592,525 )
> Search Columns: 2
> Estim. CPU-Costs = 789,224,817 Estim. IO-Costs = 5,101
> Access Predicates Filter Predicates
Ok, we've no restriction to the data, so Oracle chooses the access methods it thinks are best for large volumes of data - Full table scans and HASH JOINS. The index skip scan is quite odd - maybe this is due to one of the join conditions.
> Explain plan for QAS:
>
SELECT STATEMENT ( Estimated Costs = 263,249 , Estimated #Rows = 13,842,540 )
>
> 7 HASH JOIN
> ( Estim. Costs = 263,249 , Estim. #Rows = 13,842,540 )
> Estim. CPU-Costs = 59,041,893,935 Estim. IO-Costs = 260,190
> Access Predicates
>
> 1 TABLE ACCESS FULL LFA1
> ( Estim. Costs = 63 , Estim. #Rows = 812 )
> Estim. CPU-Costs = 7,478,316 Estim. IO-Costs = 63
> Filter Predicates
> 6 HASH JOIN
> ( Estim. Costs = 263,113 , Estim. #Rows = 13,842,540 )
> Estim. CPU-Costs = 57,640,387,953 Estim. IO-Costs = 260,127
> Access Predicates
>
> 4 HASH JOIN
> ( Estim. Costs = 2,127 , Estim. #Rows = 194,660 )
> Estim. CPU-Costs = 513,706,489 Estim. IO-Costs = 2,100
> Access Predicates
>
> 2 TABLE ACCESS FULL EIKP
> ( Estim. Costs = 351 , Estim. #Rows = 54,830 )
> Estim. CPU-Costs = 49,504,995 Estim. IO-Costs = 348
> Filter Predicates
> 3 TABLE ACCESS FULL EKKO
> ( Estim. Costs = 1,534 , Estim. #Rows = 194,660 )
> Estim. CPU-Costs = 401,526,622 Estim. IO-Costs = 1,513
> Filter Predicates
>
> 5 TABLE ACCESS FULL EKPO
> ( Estim. Costs = 255,339 , Estim. #Rows = 3,631,800 )
> Estim. CPU-Costs = 55,204,047,516 Estim. IO-Costs = 252,479
> Filter Predicates
Ok, we see significantly different table sizes here, but at least this second plan leaves out the superfluous Index Skip Scan.
How to move on from here?
1. Check whether you've installed all the current patches. Not all bugs that are in the system are hit all the time, so it may very well be that after new CBO stats were calculated you just begin to hit one of it.
2. Make sure that all parameter recommendations are implemented on the systems. This is crucial for the CBO.
3. Provide a description of the Indexes and the view definition.
The easiest would be: perform an Oracle CBO trace and provide a download link to it.
regards,
Lars
Maybe you are looking for
-
Itunes 9.2: CDs appear, disappear, appear, then disappear
I'm using external CD/DVD drives with my MacBook Pro (modded to remove internal drive). They worked fine until the latest software updates. Now CDs mount in the Finder, but when iTunes starts: 1. iTunes starts querying GraceNote 2. the CD disappears
-
N73 Firmware upgrade--- bad working Voice dialing
I updated the firmware of my Nokia N73 from 268.0.0.3 to 368.0.0.1. With the older version delivered by the phone voice dialing worked. In the 268.0.0.3 I only could given voice command for the profiles not for the contacts. It didn't recognise any c
-
I have Jdbc code which is running fine as a stand alone program. When i integrated it with an apllet it gives me access denied (java.lang.RuntimePermission accessClassInPackage.sun.jdbc.odbc) I m using netbeans. 3.6 The intersting thing is the code r
-
Hi all, When trying to transfer forecast to R/3 from Demand Planning, I am getting a successful transfer message. but Independent requirements are not showing up in R/3. I have created a activity and schedules a background job for the transfer. Are t
-
My MacBook Pro is admittedly old (2009) but suddenly very slow when using LR4
I don't hve the fastest computer, admittedly. But dowloading raw pics cand take ten minutes per picture. I am downloading to an external drive - is that the problem, or do I simply need to get a more modern/ faster computer? I typically shoot in ra