Skip to Main Content
  • Questions
  • ORA-06503: PL/SQL: Function returned without value

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Shri.

Asked: September 14, 2006 - 11:22 am UTC

Last updated: November 22, 2006 - 3:54 pm UTC

Version: 10.2.0.1.0

Viewed 10K+ times! This question is

You Asked

Tom,

I am having this problem since a months and I am stuck after Oracle upgrade from 9i to 10g not able to figure out what's going wrong. I have a function which runs fine on Oracle 9i but error out "ORA-06503: PL/SQL: Function returned without value" in 10g. The function status is VALID, no compilation error..
Maybe I am over looking it or some absolute syntax is use in 10g ... not sure what's happening ... appreciate your help.

Here is the function code :

###

CREATE OR REPLACE FUNCTION getPriceAdjustment_Func(userID IN NUMBER, subjProp IN NUMBER,comp1Prop IN NUMBER,comp2Prop IN NUMBER,comp3Prop IN NUMBER)
RETURN types.ref_cursor
IS
amt AMOUNT_ADJUSTMENT_REF.amount%TYPE;
baths_amt AMOUNT_ADJUSTMENT_REF.amount%TYPE;
myCursor types.ref_cursor;

priceAdjCur types.ref_cursor;




BEGIN
DBMS_OUTPUT.PUT_LINE(' Ready to create view - Comp_Adj_Amt_Profile_view ');
EXECUTE IMMEDIATE
'CREATE OR REPLACE VIEW Comp_Adj_Amt_Profile_view AS
SELECT a.ITEM , a.VALUE, a.SALE_PRICE_RANGE_ID, DECODE(b.dollar_adjustment, null, a.AMOUNT , b.DOLLAR_ADJUSTMENT ) AS FINAL_ADJUSTENT
FROM AMOUNT_ADJUSTMENT_REF a
FULL OUTER JOIN
(SELECT ITEM, VALUE, SALE_PRICE, DOLLAR_ADJUSTMENT FROM PRICE_RNG_ADJSTMNT_PROFILE where user_id =' || userID ||
') b
ON a.item = b.item
AND a.value = b.value
AND a.SALE_PRICE_RANGE_ID = b.sale_price
ORDER BY a.ITEM, a.SALE_PRICE_RANGE_ID,a.VALUE';

SELECT FINAL_ADJUSTENT INTO amt from Comp_Adj_Amt_Profile_view
WHERE ITEM = 'baths'
AND VALUE = '.5'
AND SALE_PRICE_RANGE_ID = 'A';

DBMS_OUTPUT.PUT_LINE(' amount = ' || amt);

OPEN priceAdjCur FOR
'SELECT RHS.rdata_number,
RHS_garage_amount,LHS_garage_amount ,(LHS_garage_amount - RHS_garage_amount) as garage_amt_diff,
RHS_bath_amount,LHS_bath_amount ,(LHS_bath_amount - RHS_bath_amount) as bath_amt_diff,
RHS_heating_amount,LHS_heating_amount ,(LHS_heating_amount - RHS_heating_amount) as heating_amt_diff,
RHS_construction_amount,LHS_construction_amount ,(LHS_construction_amount - RHS_construction_amount) as construction_amt_diff,
RHS_cooling_amount,LHS_cooling_amount ,(LHS_cooling_amount - RHS_cooling_amount) as cooling_amt_diff,
RHS_fireplace_amount,LHS_fireplace_amount ,(LHS_fireplace_amount - RHS_fireplace_amount) as fireplace_amt_diff,
RHS_bed_amount,LHS_bed_amount ,(LHS_bed_amount - RHS_bed_amount) as bed_amt_diff

FROM
(SELECT a.rdata_number, garage_amount as RHS_garage_amount,
heating_amount as RHS_heating_amount,
bath_amount as RHS_bath_amount,
construction_amount as RHS_construction_amount,
cooling_amount as RHS_cooling_amount,
fp_amount as RHS_fireplace_amount,
bed_amount as RHS_bed_amount

FROM
(select unique rd.rdata_number, Comp_Adj_Amt_Profile_view.item, Comp_Adj_Amt_Profile_view.FINAL_ADJUSTENT AS garage_amount, rr.sale_price,
(
SELECT max(sale_price_range_id)
FROM sale_price_range_ref
WHERE rr.sale_price > sale_price_low) as sale_price_range_id_here
FROM rdata_comp_ref rr, Comp_Adj_Amt_Profile_view, rdata_dump rd, sale_price_range_ref sr
WHERE rd.rdata_number = rr.rdata_number
AND rr.RDATA_NUMBER IN (' || comp1Prop || ',' || comp2Prop || ',' || comp3Prop || ')' ||'
AND lower(NVL(rr.garage_details,''-'')) = Comp_Adj_Amt_Profile_view.VALUE
AND Comp_Adj_Amt_Profile_view.ITEM = ''garage''
AND Comp_Adj_Amt_Profile_view.sale_price_range_id =
(select max(sale_price_range_id) from sale_price_range_ref where rr.sale_price > sale_price_low)) a,

(select unique rd.rdata_number, Comp_Adj_Amt_Profile_view.item, Comp_Adj_Amt_Profile_view.FINAL_ADJUSTENT as bath_amount, rr.sale_price ,
(
select max(sale_price_range_id)
FROM sale_price_range_ref
WHERE rr.sale_price > sale_price_low) as sale_price_range_id_here
FROM rdata_comp_ref rr, Comp_Adj_Amt_Profile_view, rdata_dump rd, sale_price_range_ref sr
WHERE rd.rdata_number = rr.rdata_number
AND rr.RDATA_NUMBER IN (' || comp1Prop || ',' || comp2Prop || ',' || comp3Prop || ')' ||'
AND ''.5'' = Comp_Adj_Amt_Profile_view.VALUE
AND Comp_Adj_Amt_Profile_view.ITEM = ''baths''
AND Comp_Adj_Amt_Profile_view.sale_price_range_id =
(select max(sale_price_range_id) from sale_price_range_ref where rr.sale_price > sale_price_low)) b,


(select unique rd.rdata_number, Comp_Adj_Amt_Profile_view.item, Comp_Adj_Amt_Profile_view.FINAL_ADJUSTENT as heating_amount, rr.sale_price ,
(
select max(sale_price_range_id)
FROM sale_price_range_ref
WHERE rr.sale_price > sale_price_low) as sale_price_range_id_here
FROM rdata_comp_ref rr, Comp_Adj_Amt_Profile_view, rdata_dump rd, sale_price_range_ref sr
WHERE rd.rdata_number = rr.rdata_number
AND rr.RDATA_NUMBER IN (' || comp1Prop || ',' || comp2Prop || ',' || comp3Prop || ')' ||'
AND lower(NVL(rr.heating_type,''-'')) = Comp_Adj_Amt_Profile_view.VALUE
AND Comp_Adj_Amt_Profile_view.ITEM = ''heating''
AND Comp_Adj_Amt_Profile_view.sale_price_range_id =
(select max(sale_price_range_id) from sale_price_range_ref where rr.sale_price > sale_price_low)) c,


(select unique rd.rdata_number, Comp_Adj_Amt_Profile_view.item, Comp_Adj_Amt_Profile_view.FINAL_ADJUSTENT as construction_amount, rr.sale_price,
(
select max(sale_price_range_id)
FROM sale_price_range_ref
WHERE rr.sale_price > sale_price_low) as sale_price_range_id_here
FROM rdata_comp_ref rr, Comp_Adj_Amt_Profile_view, rdata_dump rd, sale_price_range_ref sr
WHERE rd.rdata_number = rr.rdata_number
AND rr.RDATA_NUMBER IN (' || comp1Prop || ',' || comp2Prop || ',' || comp3Prop || ')' ||'
AND lower(NVL(rr.construction,''-'')) = Comp_Adj_Amt_Profile_view.VALUE
AND Comp_Adj_Amt_Profile_view.ITEM = ''construction''
AND Comp_Adj_Amt_Profile_view.sale_price_range_id =
(select max(sale_price_range_id) from sale_price_range_ref where rr.sale_price > sale_price_low)) d,


(select unique rd.rdata_number, Comp_Adj_Amt_Profile_view.item, Comp_Adj_Amt_Profile_view.FINAL_ADJUSTENT as cooling_amount, rr.sale_price ,
(
select max(sale_price_range_id)
FROM sale_price_range_ref
WHERE rr.sale_price > sale_price_low) as sale_price_range_id_here
FROM rdata_comp_ref rr, Comp_Adj_Amt_Profile_view, rdata_dump rd, sale_price_range_ref sr
WHERE rd.rdata_number = rr.rdata_number
AND rr.RDATA_NUMBER IN (' || comp1Prop || ',' || comp2Prop || ',' || comp3Prop || ')' ||'
AND lower(NVL(rr.cooling_type,''-'')) = Comp_Adj_Amt_Profile_view.VALUE
AND Comp_Adj_Amt_Profile_view.ITEM = ''cooling''
AND Comp_Adj_Amt_Profile_view.sale_price_range_id =
(select max(sale_price_range_id) from sale_price_range_ref where rr.sale_price > sale_price_low)) e,

(select unique rd.rdata_number, Comp_Adj_Amt_Profile_view.item, Comp_Adj_Amt_Profile_view.FINAL_ADJUSTENT as fp_amount, rr.sale_price ,
(
select max(sale_price_range_id)
FROM sale_price_range_ref
WHERE rr.sale_price > sale_price_low) as sale_price_range_id_here
FROM rdata_comp_ref rr, Comp_Adj_Amt_Profile_view, rdata_dump rd, sale_price_range_ref sr
WHERE rd.rdata_number = rr.rdata_number
AND rr.RDATA_NUMBER IN (' || comp1Prop || ',' || comp2Prop || ',' || comp3Prop || ')' ||'
AND lower(NVL(rr.type_of_fireplace,''-'')) = Comp_Adj_Amt_Profile_view.VALUE
AND Comp_Adj_Amt_Profile_view.ITEM = ''fireplace''
AND Comp_Adj_Amt_Profile_view.sale_price_range_id =
(select max(sale_price_range_id) from sale_price_range_ref where rr.sale_price > sale_price_low)) f,

(select unique rd.rdata_number, Comp_Adj_Amt_Profile_view.item, Comp_Adj_Amt_Profile_view.FINAL_ADJUSTENT as bed_amount, rr.sale_price ,
(
select max(sale_price_range_id)
FROM sale_price_range_ref
WHERE rr.sale_price > sale_price_low) as sale_price_range_id_here
FROM rdata_comp_ref rr, Comp_Adj_Amt_Profile_view, rdata_dump rd, sale_price_range_ref sr
WHERE rd.rdata_number = rr.rdata_number
AND rr.RDATA_NUMBER IN (' || comp1Prop || ',' || comp2Prop || ',' || comp3Prop || ')' ||'
AND lower(NVL(rr.no_of_bedrm,''-'')) = Comp_Adj_Amt_Profile_view.VALUE
AND Comp_Adj_Amt_Profile_view.ITEM = ''beds''
AND Comp_Adj_Amt_Profile_view.sale_price_range_id =
(select max(sale_price_range_id) from sale_price_range_ref where rr.sale_price > sale_price_low)) g


WHERE
a.rdata_number = b.rdata_number
AND b.rdata_number = c.rdata_number
AND c.rdata_number = d.rdata_number
AND d.rdata_number = e.rdata_number
AND e.rdata_number = f.rdata_number
AND f.rdata_number = g.rdata_number
AND a.RDATA_NUMBER IN (' || comp1Prop || ',' || comp2Prop || ',' || comp3Prop || ')' ||'
)
RHS,

(SELECT a.rdata_number, garage_amount as LHS_garage_amount,
bath_amount as LHS_bath_amount,
heating_amount as LHS_heating_amount,
construction_amount as LHS_construction_amount,
cooling_amount as LHS_cooling_amount,
fp_amount as LHS_fireplace_amount,
bed_amount as LHS_bed_amount



FROM
(select unique rd.rdata_number, Comp_Adj_Amt_Profile_view.item, Comp_Adj_Amt_Profile_view.FINAL_ADJUSTENT as garage_amount, rr.sale_price,
(
select max(sale_price_range_id)
FROM sale_price_range_ref
WHERE rr.sale_price > sale_price_low) as sale_price_range_id_here
FROM rdata_comp_ref rr, Comp_Adj_Amt_Profile_view, rdata_dump rd, sale_price_range_ref sr
WHERE rd.rdata_number = rr.rdata_number
AND lower(NVL(rr.garage_details,''-'')) = Comp_Adj_Amt_Profile_view.VALUE
AND Comp_Adj_Amt_Profile_view.ITEM = ''garage''
AND rr.RDATA_NUMBER = ' || subjProp ||'
AND Comp_Adj_Amt_Profile_view.sale_price_range_id =
(select max(sale_price_range_id) from sale_price_range_ref where rr.sale_price > sale_price_low)) a,

(select unique rd.rdata_number, Comp_Adj_Amt_Profile_view.item, Comp_Adj_Amt_Profile_view.FINAL_ADJUSTENT as bath_amount, rr.sale_price ,
(
select max(sale_price_range_id)
FROM sale_price_range_ref
WHERE rr.sale_price > sale_price_low) as sale_price_range_id_here
FROM rdata_comp_ref rr, Comp_Adj_Amt_Profile_view, rdata_dump rd, sale_price_range_ref sr
WHERE rd.rdata_number = rr.rdata_number
AND ''.5'' = Comp_Adj_Amt_Profile_view.VALUE
AND Comp_Adj_Amt_Profile_view.ITEM =''baths''
AND rr.RDATA_NUMBER = ' || subjProp ||'
AND Comp_Adj_Amt_Profile_view.sale_price_range_id =
(select max(sale_price_range_id) from sale_price_range_ref where rr.sale_price > sale_price_low)) b,


(select unique rd.rdata_number, Comp_Adj_Amt_Profile_view.item, Comp_Adj_Amt_Profile_view.FINAL_ADJUSTENT as heating_amount, rr.sale_price,
(
select max(sale_price_range_id)
FROM sale_price_range_ref
WHERE rr.sale_price > sale_price_low) as sale_price_range_id_here
FROM rdata_comp_ref rr, Comp_Adj_Amt_Profile_view, rdata_dump rd, sale_price_range_ref sr
WHERE rd.rdata_number = rr.rdata_number
AND lower(NVL(rr.heating_type,''-'')) = Comp_Adj_Amt_Profile_view.VALUE
AND Comp_Adj_Amt_Profile_view.ITEM = ''heating''
AND rr.RDATA_NUMBER = ' || subjProp ||'
AND Comp_Adj_Amt_Profile_view.sale_price_range_id =
(select max(sale_price_range_id) from sale_price_range_ref where rr.sale_price > sale_price_low)) c,


(select unique rd.rdata_number, Comp_Adj_Amt_Profile_view.item, Comp_Adj_Amt_Profile_view.FINAL_ADJUSTENT as construction_amount, rr.sale_price,
(
select max(sale_price_range_id)
FROM sale_price_range_ref
WHERE rr.sale_price > sale_price_low) as sale_price_range_id_here
FROM rdata_comp_ref rr, Comp_Adj_Amt_Profile_view, rdata_dump rd, sale_price_range_ref sr
WHERE rd.rdata_number = rr.rdata_number
AND lower(NVL(rr.construction,''-'')) = Comp_Adj_Amt_Profile_view.VALUE
AND Comp_Adj_Amt_Profile_view.ITEM = ''construction''
AND rr.RDATA_NUMBER = ' || subjProp ||'
AND Comp_Adj_Amt_Profile_view.sale_price_range_id =
(select max(sale_price_range_id) from sale_price_range_ref where rr.sale_price > sale_price_low)) d,

(select unique rd.rdata_number, Comp_Adj_Amt_Profile_view.item, Comp_Adj_Amt_Profile_view.FINAL_ADJUSTENT as cooling_amount, rr.sale_price ,
(
select max(sale_price_range_id)
FROM sale_price_range_ref
WHERE rr.sale_price > sale_price_low) as sale_price_range_id_here
FROM rdata_comp_ref rr, Comp_Adj_Amt_Profile_view, rdata_dump rd, sale_price_range_ref sr
WHERE rd.rdata_number = rr.rdata_number
AND lower(NVL(rr.cooling_type,''-'')) = Comp_Adj_Amt_Profile_view.VALUE
AND Comp_Adj_Amt_Profile_view.ITEM = ''cooling''
AND rr.RDATA_NUMBER = ' || subjProp ||'
AND Comp_Adj_Amt_Profile_view.sale_price_range_id =
(select max(sale_price_range_id) from sale_price_range_ref where rr.sale_price > sale_price_low)) e,

(select unique rd.rdata_number, Comp_Adj_Amt_Profile_view.item, Comp_Adj_Amt_Profile_view.FINAL_ADJUSTENT as fp_amount, rr.sale_price ,
(
select max(sale_price_range_id)
FROM sale_price_range_ref
WHERE rr.sale_price > sale_price_low) as sale_price_range_id_here
FROM rdata_comp_ref rr, Comp_Adj_Amt_Profile_view, rdata_dump rd, sale_price_range_ref sr
WHERE rd.rdata_number = rr.rdata_number
AND rr.RDATA_NUMBER = ' || subjProp ||'
AND lower(NVL( rr.type_of_fireplace,''-'')) = Comp_Adj_Amt_Profile_view.VALUE
AND Comp_Adj_Amt_Profile_view.ITEM = ''fireplace''
AND Comp_Adj_Amt_Profile_view.sale_price_range_id =
(select max(sale_price_range_id) from sale_price_range_ref where rr.sale_price > sale_price_low)) f,

(select unique rd.rdata_number, Comp_Adj_Amt_Profile_view.item, Comp_Adj_Amt_Profile_view.FINAL_ADJUSTENT as bed_amount, rr.sale_price,
(
select max(sale_price_range_id)
FROM sale_price_range_ref
WHERE rr.sale_price > sale_price_low) as sale_price_range_id_here
FROM rdata_comp_ref rr, Comp_Adj_Amt_Profile_view, rdata_dump rd, sale_price_range_ref sr
WHERE rd.rdata_number = rr.rdata_number
AND rr.RDATA_NUMBER = ' || subjProp ||'
AND lower(NVL( rr.no_of_bedrm,''-'')) = Comp_Adj_Amt_Profile_view.VALUE
AND Comp_Adj_Amt_Profile_view.ITEM = ''beds''
AND Comp_Adj_Amt_Profile_view.sale_price_range_id =
(select max(sale_price_range_id) from sale_price_range_ref where rr.sale_price > sale_price_low)) g
WHERE
a.rdata_number = b.rdata_number
AND b.rdata_number = c.rdata_number
AND c.rdata_number = d.rdata_number
AND d.rdata_number = e.rdata_number
AND e.rdata_number = f.rdata_number
AND f.rdata_number = g.rdata_number
AND a.RDATA_NUMBER = ' || subjProp ||'
)
LHS';


DBMS_OUTPUT.PUT_LINE(' amount baths = ' || baths_amt);
RETURN priceAdjCur;

EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.PUT_LINE(' Error is getPriceAdjustment_Func procedure ' || SQLERRM);


END;
/


###

Please let me know if you need any more informations.

Your help on this will be appreciated.

Thanks in Advance,
Shri.


and Tom said...

good gosh - you could not whittle that down?

Here is what is happening.


When you have an error, the control jumps to the evil, dreaded, hateful, very very bad, should never be there, must be ERASED IMMEDIATELY when others block you have.

When control jumps there - you just hid the error message from view.

And you use dbms_output (which is really only effective in sqlplus), to 'print' an error message - but you HIDE THE ERROR FROM THE CLIENT!!!!!!

And you return - nothing, nada, zippo

hence,

a) you have an error being thrown in the code
b) you have TOTALLY HIDDEN IT WITH THAT HORRID WHEN OTHERS block
c) you return nothing in the when others.


My suggestion to you is

a) immediately review all code you have access to
b) any WHEN OTHERS that you see that IS NOT FOLLOWED BY RAISE - add "raise;" to the block
c) better yet - any WHEN OTHERS you see, erase, just get rid of it, remove it. It is a BUG IN YOUR DEVELOPED CODE


thank goodness you didn't return anything, that would have been really bad as the error would go unnoticed forever.


stop using when others (that are not followed by RAISE; to re-raise the exception!!!!!!)




that and what is UP WITH THE CREATE VIEW????!?!??! I don't know how that code ever worked - get rid of that immediately, do NOT do ddl in production code that way - that is almost as bad as when others.


and oh my gosh - no bind variables either?!?!?


you have just ruined my entire day with this one - sorry if you feel this is harsh, but this is an example of how not to do things.


Ok, I feel compelled to get some of this corrected.

That view - it is GOING AWAY, zero percent chance I will let you use it. Your first select into, it should simply be:

select nvl( b.dollar_adjustment, a.amount )
INTO amt
from amount_adjustment_ref a,
(select ITEM, VALUE, SALE_PRICE, DOLLAR_ADJUSTMENT
FROM PRICE_RNG_ADJSTMNT_PROFILE
where user_id = p_userID) b
where a.item = b.item (+)
and a.value = b.value (+)
and a.sale_price_range_id = b.sale_price (+)
and a.item = 'baths'
and a.value = '.5'
and a.sale_price_range_id = 'A';


You do NOT want a full outer join, you have a predicate directly against a.item, a.value and a.sale_price_range_id clearly in your code (and that order by in the view? Just to make it have even more overhead??). That select into does the same thing as your existing code - only it'll likely be "easier for the optimizer to digest and make sense of).


And that big big big query - well, I don't have the time to rewrite it for you - however, please take this snippet of code to heart:


ops$tkyte%ORA9IR2> create or replace function f( p_input in number ) return sys_refcursor
2 as
3 l_cursor sys_refcursor;
4 begin
5 open l_cursor
6 for
7 with your_view
8 as
9 (select * from all_users)
10 select *
11 from your_view
12 where user_id = p_input;
13
14 return l_cursor;
15 end;
16 /

Function created.

ops$tkyte%ORA9IR2>
ops$tkyte%ORA9IR2> variable x refcursor
ops$tkyte%ORA9IR2> exec :x := f(5);

PL/SQL procedure successfully completed.

ops$tkyte%ORA9IR2> print x;

USERNAME USER_ID CREATED
------------------------------ ---------- ---------
SYSTEM 5 06-DEC-03



a) use WITH - NOT CREATE VIEW
b) use BINDS (p_input is a bind) - NOT STRING CONCATENATION
c) use STATIC SQL - you have zero need for dynamic sql here

Rating

  (8 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Great job Tom.

Manish Sohaney, September 15, 2006 - 10:49 am UTC

Tom - You are simply the best. I really appreciate your time and let other's leverage your expertise.

Keep up the good work.



Maybe the error is not that helpful

joel garry, September 15, 2006 - 2:29 pm UTC

It looks as if this code was created in sqlplus, "worked" (well, at least gave output), and then was put as-is into a function. Perhaps the real problem is that it is difficult to tell when sqlplus is not sql.

So perhaps sqlplus needs a setting to make it more obvious when sql is not being used. Or maybe the same in the function compiler.

These are things the language should tell the programmer, rather than the programmer should be expected to mysteriously know.

Tom Kyte
September 16, 2006 - 2:22 pm UTC

nope, even in sqlplus, this would return the ora error that function returned without a value.

it wouldn't be any different.

this is just 100% a case of "when others" not followed by "raise" hiding a bug in the developed code. Happens everytime.

Why the "do NOT do ddl in production code" ???

Phil, September 18, 2006 - 12:24 pm UTC

Hi Tom,

I see that you are vehemently opposed to performing DDL in production PL/SQL code - and I agree with the instance for this question - specifically the "CREATE VIEW"...

I have read 3 of your books - and I notice your opposition to DDL in PL/SQL in them - but I can't find where you explain the "Why" not do this.

Could you elaborate on why we shouldn't do it - other than to say "it is bad"?

The reason I ask is that I had to find a way to "boost" Materialized View refresh performance (over using DBMS_MVIEW.REFRESH). I tried things you recommended - such as disabling all indexes - refreshing the Mat. View - then re-enabling the indexes, etc - but still didn't get the desired performance.

I then experimented and found that when I used a "CREATE TABLE AS SELECT" with the Mat. View query - it created nearly 3 times faster (33% of the time) on average (these are "BIG" (50 million rows+) datawarehouse Mat. Views).

So - I reverse engineered the DMBS_METADATA package and found the Oracle XSL stylesheets used to convert XML attributes about tables into "DDL" - I changed them to allow one to pass in "new" attributes such as "new table name", etc. so you could create a table with a different name using calls to DBMS_METADATA - but with IDENTICAL structure, indexing, partitioning, etc. - effectively letting you "Clone" a Materialized View's DDL. I then provide the capability to pass in a Query to this function (it will then remove the column TYPEs as is necessary in a CTAS statement) - in this instance: the Materialized View query (from USER_MVIEWS view - query field) - so I am creating a table with identical indexing, partitioning, and (fresh) contents (since it becomes a "CREATE TABLE AS SELECT" statement) - then I can simply replace the Materialized View by 1) dropping it 2) renaming my new "temp table" 3) using "ON PREBUILT TABLE" option.

I know you probably won't like this approach - but run times of 33% of what they were before are hard to argue with. Am I off base here?

Thank you as always sir.

Tom Kyte
September 18, 2006 - 1:45 pm UTC

doing ddl invalidates all dependent objects.
doing ddl makes it really hard to have plsql routines that work reliably.
doing ddl in most every case is something that can easily be avoided.

with a materialized view refreshed infrequently, it might be an "OK" thing since you won't have views/stored procedures that reference them - you'll just invalidate cursors against them (which would happen anyway as you gather statistics after a refresh...)

ORA-06503: PL/SQL: Function returned without value

Shriram Yadav, September 19, 2006 - 3:33 pm UTC

Thanks for all your supports. I appreciate it.

-Shri

wow

Robert, September 20, 2006 - 10:31 pm UTC

wholey cow
dude don't let ANYONE at work see that code ! LOL
you aware your DDL also causes an *immediate* COMMIT ?
and suggest you look into "parameterized View" using SYS_CONTEXT

ORA-06503: PL/SQL: Function returned without value

Amit, November 21, 2006 - 1:31 pm UTC

Hi Tom,

I am facing the error in the below package :

ORA-06503: PL/SQL: Function returned without value
ORA-06512: at "STRMADMIN.REPLICATION_DIFF", line 534
ORA-06512: at line 1
CREATE OR REPLACE PACKAGE BODY replication_diff AS

TYPE v50_table IS TABLE OF VARCHAR2(150) INDEX BY BINARY_INTEGER;

FUNCTION open_file(dir_name VARCHAR2,
file_name VARCHAR2,
append_file BOOLEAN)
RETURN UTL_FILE.FILE_TYPE IS
FileHandle UTL_FILE.FILE_TYPE;
BEGIN
dbms_output.put_line('Opening file');
IF (append_file) THEN
FileHandle := UTL_FILE.FOPEN(dir_name, file_name, 'a');
ELSE
FileHandle := UTL_FILE.FOPEN(dir_name, file_name, 'w');
END IF;
RETURN(FileHandle);
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('ERROR in opening file '||dir_name||','||file_name);
DBMS_OUTPUT.PUT_LINE('ERROR in opening file:'||TO_CHAR(SQLCODE));
DBMS_OUTPUT.PUT_LINE('ERROR in opening file:'||SQLERRM);
END;

FUNCTION subset_str(full_str IN OUT VARCHAR2, subset_str IN OUT VARCHAR2, look_str VARCHAR2,no_of_chars INTEGER) RETURN VARCHAR2 is
loc PLS_INTEGER := 0;
pre_loc PLS_INTEGER := 0;
i PLS_INTEGER := 1;
BEGIN
if (instr(full_str,look_str,1)=0) then
return(1);
end if;
if (NVL(length(full_str),0) <= no_of_chars) then
subset_str := full_str;
full_str := '';
return(0);
end if;
loop
loc := instr(full_str,look_str,1,i);
--dbms_output.put_line('loc = '||loc);
if ((loc > no_of_chars) OR (loc = 0)) then
exit;
end if;
if (i > 400) then
dbms_output.put_line('Exceeding the limit....');
exit;
end if;
pre_loc := loc;
i := i + 1;
end loop;
subset_str := substr(full_str,1,pre_loc-1);
full_str := substr(full_str,pre_loc);
return(0);
END;

PROCEDURE print(str VARCHAR2) IS
len PLS_INTEGER;
BEGIN
len := NVL(LENGTH(str),0);
FOR i in 1..len LOOP
DBMS_OUTPUT.PUT_LINE(SUBSTR(str,(i-1)*255,255));
END LOOP;
IF ((len*255) > LENGTH(str)) THEN
DBMS_OUTPUT.PUT_LINE(SUBSTR(str,len*255));
END IF;
END;

PROCEDURE init_file(dir_name VARCHAR2,
file_name VARCHAR2)
IS
FileHandle UTL_FILE.FILE_TYPE;
BEGIN
FileHandle := open_file(dir_name,file_name,FALSE);
UTL_FILE.FCLOSE(FileHandle);
END;

PROCEDURE set_switch_off(fd UTL_FILE.FILE_TYPE,slink varchar2,tlink varchar2) IS
BEGIN
UTL_FILE.PUTF(fd,'\nwhenever sqlerror exit sqlcode\n');
UTL_FILE.PUTF(fd,'exec dbms_reputil.replication_off@%s\n',slink);
UTL_FILE.PUTF(fd,'exec repconflict_tmstp_pkg.update_timestamp_off@%s\n',slink);
UTL_FILE.PUTF(fd,'exec dbms_streams.set_tag@%s(tag => HEXTORAW(''1D''))\n',slink);
UTL_FILE.PUTF(fd,'exec dbms_reputil.replication_off@%s\n',tlink);
UTL_FILE.PUTF(fd,'exec repconflict_tmstp_pkg.update_timestamp_off@%s\n',tlink);
UTL_FILE.PUTF(fd,'exec dbms_streams.set_tag@%s(tag => HEXTORAW(''1D''))\n',tlink);
UTL_FILE.PUTF(fd,'\nwhenever sqlerror continue\n');
END;

PROCEDURE get_columns(sschema VARCHAR2,
stable VARCHAR2,
cols OUT col_tab)
IS
CURSOR col_cur(sname VARCHAR2, oname VARCHAR2) IS
SELECT column_name, data_type
FROM dba_tab_columns
WHERE owner=sname AND
table_name = oname
ORDER BY column_id;
idx PLS_INTEGER := 1;
BEGIN
FOR row IN col_cur(sschema,stable) LOOP
cols(idx).col_name := row.column_name;
cols(idx).col_type := row.data_type;
cols(idx).pos := idx;
idx := idx + 1;
END LOOP;
END;

PROCEDURE table_minus_table(table1 col_tab,
table2 col_tab,
out_table OUT col_tab)
IS
BEGIN
out_table := table1;
IF (table2.COUNT = 0) THEN
RETURN;
END IF;
FOR i IN 1..out_table.COUNT LOOP
FOR j IN 1..table2.COUNT LOOP
IF (out_table(i).col_name = table2(j).col_name) THEN
out_table.DELETE(i);
END IF;
END LOOP;
END LOOP;
END;
FUNCTION get_col_str(cols col_tab,
delimiter char,
prefix VARCHAR2,
postfix VARCHAR)
RETURN VARCHAR2 IS
out_str VARCHAR2(32000);
BEGIN
FOR i IN 1..cols.COUNT LOOP
IF (out_str IS NULL) THEN
out_str := prefix||cols(i).col_name||postfix;
ELSE
out_str := out_str||delimiter||prefix||cols(i).col_name||postfix;
END IF;
END LOOP;
RETURN(out_str);
END;

FUNCTION diff_table_internal(sschema VARCHAR2,
stable VARCHAR2,
slink VARCHAR2,
tschema VARCHAR2,
ttable VARCHAR2,
tlink VARCHAR2,
keycols VARCHAR2,
diff_file_handle UTL_FILE.FILE_TYPE,
fix_file_handle UTL_FILE.FILE_TYPE,
diff_limit NUMBER ,
where_clause_1 VARCHAR2,
where_clause_2 VARCHAR2,
where_clause_3 VARCHAR2,
columns_list VARCHAR2,
skip_columns VARCHAR2,
commit_batch NUMBER,
timestamp_col VARCHAR2,
check_again BOOLEAN,
diff_table_nm VARCHAR2,
compare_tmstp BOOLEAN )
RETURN NUMBER;

FUNCTION get_key(sname VARCHAR2, oname VARCHAR2)
RETURN VARCHAR2 IS
CURSOR pkeys_cur(sname VARCHAR2, oname VARCHAR2) IS
SELECT column_name
FROM dba_constraints a, dba_cons_columns b
WHERE a.constraint_name=b.constraint_name AND
a.owner = b.owner AND
a.owner = sname AND
a.constraint_type='P' AND
a.table_name=oname
ORDER BY position;
key_str VARCHAR2(500);
BEGIN
FOR i IN pkeys_cur(sname,oname) LOOP
IF (key_str IS NULL) THEN
key_str := i.column_name;
ELSE
key_str := key_str||','||i.column_name;
END IF;
END LOOP;
RETURN(key_str);
END;

PROCEDURE get_table_for_str(
p_arr OUT v50_table ,
p_string VARCHAR2,
delim VARCHAR2 := ',',
enclose_str VARCHAR2 DEFAULT NULL)
IS
pos INTEGER := 1;
v_idx INTEGER := 1;
tmp_str VARCHAR2(4000);
BEGIN
IF p_string IS NULL THEN
return;
END IF;
tmp_str := p_string;
LOOP
EXIT WHEN (pos = 0);
pos := INSTR(tmp_str,delim);
IF (pos = 0) THEN
p_arr(v_idx) := enclose_str||tmp_str||enclose_str;
ELSE
p_arr(v_idx) := enclose_str||SUBSTR(tmp_str,1,pos-1)||enclose_str;
v_idx := v_idx + 1;
tmp_str := SUBSTR(tmp_str,pos+1);
END IF;
END LOOP;
END;

FUNCTION getcols(sname VARCHAR2, tname VARCHAR2) RETURN VARCHAR2 IS
columns_list v50_table;
col_str VARCHAR2(32000);
BEGIN
SELECT column_name BULK COLLECT INTO columns_list
FROM dba_tab_columns
WHERE owner=sname AND table_name=tname;
FOR i IN 1..columns_list.COUNT loop
col_str := col_str||columns_list(i)||',';
END LOOP;
RETURN(col_str);
END;

PROCEDURE diff_table(sschema VARCHAR2,
stable VARCHAR2,
slink VARCHAR2,
tschema VARCHAR2,
ttable VARCHAR2,
tlink VARCHAR2,
keycols VARCHAR2,
dir_name VARCHAR2 ,
file_name VARCHAR2,
fix_file_name VARCHAR2,
diff_limit NUMBER DEFAULT 500,
commit_batch NUMBER DEFAULT 500,
timestamp_col VARCHAR2 DEFAULT NULL,
where_clause VARCHAR2 DEFAULT NULL,
columns_list VARCHAR2 DEFAULT '*',
check_again BOOLEAN DEFAULT FALSE,
compare_tmstp BOOLEAN DEFAULT TRUE,
skip_columns VARCHAR2 DEFAULT NULL) IS
diff_file_handle UTL_FILE.FILE_TYPE;
fix_file_handle UTL_FILE.FILE_TYPE;
no_of_diff NUMBER;
where_clause_1 VARCHAR2(5000);
where_clause_2 VARCHAR2(5000);
where_clause_3 VARCHAR2(5000);
key_str VARCHAR2(500);
all_cols VARCHAR2(32000);
skip_cols_tab v50_table;
BEGIN
diff_file_handle := open_file(dir_name,file_name,FALSE);
fix_file_handle := open_file(dir_name,fix_file_name,FALSE);
IF (keycols IS NULL) THEN
key_str := get_key(sschema,stable);
ELSE
key_str := keycols;
END IF;
IF (skip_columns IS NOT NULL) THEN
all_cols := ','||getcols(sschema,stable);
get_table_for_str(skip_cols_tab,skip_columns);
FOR i IN 1..skip_cols_tab.COUNT LOOP
--all_cols := REPLACE(all_cols,skip_cols_tab(i)||',',NULL);
dbms_output.put_line('Replace='||','||skip_cols_tab(i)||',');
all_cols := REPLACE(all_cols,','||skip_cols_tab(i)||',',',');
END LOOP;
all_cols := SUBSTR(all_cols,2,length(all_cols)-2);
dbms_output.put_line('All cols='||all_cols);
ELSE
all_cols := columns_list;
END IF;
no_of_diff := diff_table_internal(sschema,stable,
slink,
tschema,
ttable,
tlink,
key_str,
diff_file_handle,
fix_file_handle,
diff_limit,
where_clause,
where_clause,
where_clause,
all_cols,
skip_columns,
commit_batch,
timestamp_col,
check_again,
stable,
compare_tmstp);
UTL_FILE.FCLOSE(diff_file_handle);
UTL_FILE.FCLOSE(fix_file_handle);
if ((check_again) AND (no_of_diff > 0)) THEN
IF (where_clause IS NULL) then
where_clause_1 := 'where ('||keycols||') in (select '||keycols||' from '||stable||'$_diff where
diff_type=''AK-BK'')';
where_clause_2 := 'where ('||keycols||') in (select '||keycols||' from '||stable||'$_diff where
diff_type=''BK-AK'')';
where_clause_3 := 'where ('||keycols||') in (select '||keycols||' from '||stable||'$_diff where
diff_type=''A-B'')';
ELSE
where_clause_1 := ' and ('||keycols||') in (select '||keycols||' from '||stable||'$_diff where
diff_type=''AK-BK'')';
where_clause_2 := ' and ('||keycols||') in (select '||keycols||' from '||stable||'$_diff where
diff_type=''BK-AK'')';
where_clause_3 := ' and ('||keycols||') in (select '||keycols||' from '||stable||'$_diff where
diff_type=''A-B'')';
END IF;
diff_file_handle := open_file(dir_name,file_name||'_1',FALSE);
fix_file_handle := open_file(dir_name,fix_file_name||'_1',FALSE);
no_of_diff := diff_table_internal(sschema,stable,
slink,
tschema,
ttable,
tlink,
key_str,
diff_file_handle,
fix_file_handle,
diff_limit,
where_clause_1,
where_clause_2,
where_clause_3,
columns_list,
NULL,
commit_batch,
timestamp_col,
FALSE,
stable||'$$_diff',
compare_tmstp);
UTL_FILE.FCLOSE(diff_file_handle);
UTL_FILE.FCLOSE(fix_file_handle);
end if;
END;


FUNCTION get_localdb RETURN varchar2 is
dbname VARCHAR2(10);
begin
select name into dbname from v$database;
return(dbname);
end;


PROCEDURE diff_group_streams(sname VARCHAR2,
dir_name VARCHAR2 ,
file_name VARCHAR2 DEFAULT NULL,
fix_file_name VARCHAR2 DEFAULT NULL,
diff_limit NUMBER DEFAULT 500,
commit_batch NUMBER DEFAULT 500,
timestamp_col VARCHAR2 DEFAULT NULL,
skip_columns VARCHAR2 DEFAULT NULL,
where_clause VARCHAR2 DEFAULT NULL,
individual_files BOOLEAN DEFAULT TRUE,
compare_tmstp BOOLEAN DEFAULT TRUE) IS

CURSOR objects_cur(sname VARCHAR2) IS
select distinct a.table_owner sname, a.table_name oname
from DBA_STREAMS_TABLE_RULES a, DBA_RULE_SET_RULES b
where a.table_owner=sname and a.streams_type='CAPTURE' and a.RULE_NAME = b.RULE_NAME
--select distinct source_object_owner sname, source_object_name oname
--from DBA_APPLY_INSTANTIATED_OBJECTS r
--where source_object_owner=sname
--and source_object_type='TABLE'
and not exists
(select 1
from dba_tab_columns c
where a.table_owner=c.owner and
a.table_name=c.table_name and
c.data_type in ('CLOB','BLOB','LONG','LONG RAW','NCLOB','XMLTYPE'));
CURSOR links_cur(sname VARCHAR2, oname VARCHAR2) IS
SELECT source_database dblink
FROM dba_apply_instantiated_objects
WHERE source_object_owner=sname AND
source_object_name=oname;
TYPE v150_table IS TABLE OF VARCHAR2(150) INDEX BY BINARY_INTEGER;
dblinks v150_table;
schemas v150_table;
objects v150_table;
skip_cols_tab v50_table;
idx NUMBER:=1;
j NUMBER;
key_cols VARCHAR2(32000);
all_cols VARCHAR2(32000);
loopCount NUMBER;
diff_file_handle UTL_FILE.FILE_TYPE;
fix_file_handle UTL_FILE.FILE_TYPE;
no_of_diff NUMBER;
whereclause VARCHAR2(5000) := ' WHERE repconflict_tmstp > sysdate - 8 ';
FUNCTION getkeys(sname VARCHAR2, oname VARCHAR2) RETURN VARCHAR2 IS
CURSOR pkeys_cur(sname VARCHAR2, oname VARCHAR2) IS
SELECT column_name
FROM dba_constraints a, dba_cons_columns b
WHERE a.constraint_name=b.constraint_name AND
a.owner = b.owner AND
a.owner = sname AND
a.constraint_type='P' AND
a.table_name=oname
ORDER BY position;
CURSOR rep_key_cols_cur(psname VARCHAR2, poname VARCHAR2) IS
SELECT column_name
FROM dba_apply_key_columns
WHERE object_owner = psname AND
object_name = poname;
key_str VARCHAR2(32000);
BEGIN
FOR i IN pkeys_cur(sname,oname) LOOP
IF (key_str IS NULL) THEN
key_str := i.column_name;
ELSE
key_str := key_str||','||i.column_name;
END IF;
END LOOP;

IF (key_str IS NULL) THEN
FOR i IN rep_key_cols_cur(sname,oname) LOOP
IF (key_str IS NULL) THEN
key_str := i.column_name;
ELSE
key_str := key_str||','||i.column_name;
END IF;
END LOOP;
END IF;
IF (key_str IS NULL) THEN
RAISE NO_DATA_FOUND;
END IF;
RETURN(key_str);
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('ERROR IN getkeys : '||TO_CHAR(SQLCODE));
RAISE;
END;
BEGIN
/*
IF (file_name IS NULL) THEN
file_name := sname||'.diff';
END IF;
IF (fix_file_name IS NULL) THEN
fix_file_name := sname||'.fix';
END IF;
*/
init_file(dir_name,NVL(file_name,sname||'.diff'));
init_file(dir_name,NVL(file_name,sname||'.fix'));
diff_file_handle := open_file(dir_name,NVL(file_name,sname||'.diff'),FALSE);
fix_file_handle := open_file(dir_name,NVL(fix_file_name,sname||'.fix'),FALSE);
idx := 1;
FOR i in objects_cur(sname) LOOP
schemas(idx) := i.sname;
objects(idx) := i.oname;
idx := idx + 1;
END LOOP;

FOR tabidx IN 1..schemas.COUNT LOOP
IF (individual_files) THEN
diff_file_handle := open_file(dir_name,objects(tabidx)||'.diff',FALSE);
fix_file_handle := open_file(dir_name,objects(tabidx)||'.fix',FALSE);
END IF;
key_cols := getkeys(schemas(tabidx),objects(tabidx));
IF (skip_columns IS NOT NULL) THEN
all_cols := ','||getcols(schemas(tabidx),objects(tabidx));
--all_cols := getcols(schemas(tabidx),objects(tabidx));
get_table_for_str(skip_cols_tab,skip_columns);
FOR i IN 1..skip_cols_tab.COUNT LOOP
--all_cols := REPLACE(all_cols,skip_cols_tab(i)||',',NULL);
dbms_output.put_line('Replace='||','||skip_cols_tab(i)||',');
all_cols := REPLACE(all_cols,','||skip_cols_tab(i)||',',',');
END LOOP;
all_cols := SUBSTR(all_cols,2,length(all_cols)-2);
dbms_output.put_line('All cols='||all_cols);
ELSE
all_cols := '*';
END IF;
dbms_output.put_line('all_cols='||substr(all_cols,1,200));

dblinks(1) := get_localdb;
idx := 2;
FOR l in links_cur(sname,objects(tabidx)) LOOP
dblinks(idx) := l.dblink;
idx := idx +1 ;
END LOOP;
IF (dblinks.COUNT = 2) THEN
LoopCount := 1;
ELSE
LoopCount := NVL(dblinks.COUNT,1)-1;
END IF;
FOR i IN 1..LoopCount LOOP
dbms_output.put_line('Processing '||schemas(tabidx)||'.'||objects(tabidx)||'@'||dblinks(1)||' AND '||schemas(tabidx)||'.'||objects(tabidx)||'@'||dblinks(i+1));
--no_of_diff := diff_table_internal(schemas(tabidx),objects(tabidx),dblinks(1),schemas(tabidx),objects(tabidx),dblinks(i+1),key_cols,diff_file_handle,fix_file_handle,diff_limit,whereclause,whereclause,whereclause,'*',commit_batch,timestamp_col,FALSE,NULL);
no_of_diff := diff_table_internal(schemas(tabidx),
objects(tabidx),
dblinks(1),
schemas(tabidx),
objects(tabidx),
dblinks(i+1),
key_cols,
diff_file_handle,
fix_file_handle,
diff_limit,
where_clause,
where_clause,
where_clause,
all_cols,
skip_columns,
commit_batch,
timestamp_col,
FALSE,
NULL,
compare_tmstp);
END LOOP;
IF (individual_files) THEN
UTL_FILE.FCLOSE(diff_file_handle);
UTL_FILE.FCLOSE(fix_file_handle);
END IF;
END LOOP;
IF NOT(individual_files) THEN
UTL_FILE.FCLOSE(diff_file_handle);
UTL_FILE.FCLOSE(fix_file_handle);
END IF;
EXCEPTION
WHEN OTHERS THEN
RAISE;
END;

PROCEDURE diff_group(groupname VARCHAR2,
dir_name VARCHAR2 ,
file_name VARCHAR2 DEFAULT NULL,
fix_file_name VARCHAR2 DEFAULT NULL,
diff_limit NUMBER DEFAULT 500,
commit_batch NUMBER DEFAULT 500,
timestamp_col VARCHAR2 DEFAULT NULL,
skip_columns VARCHAR2 DEFAULT NULL,
where_clause VARCHAR2 DEFAULT NULL,
individual_files BOOLEAN DEFAULT TRUE,
compare_tmstp BOOLEAN DEFAULT TRUE) IS
CURSOR objects_cur(groupname VARCHAR2) IS
SELECT sname, oname
FROM dba_repobject r
WHERE GNAME=groupname AND TYPE='TABLE' and not exists
(select 1
from dba_tab_columns c
where r.sname=c.owner and
r.oname=c.table_name and
c.data_type in ('CLOB','BLOB','LONG','LONG RAW','NCLOB','XMLTYPE'));
--and oname >= 'PERS%';
CURSOR links_cur(groupname VARCHAR2) IS
SELECT dblink
FROM dba_repsites
WHERE GNAME=groupname;
TYPE v150_table IS TABLE OF VARCHAR2(150) INDEX BY BINARY_INTEGER;
dblinks v150_table;
schemas v150_table;
objects v150_table;
skip_cols_tab v50_table;
idx NUMBER:=1;
j NUMBER;
key_cols VARCHAR2(500);
all_cols VARCHAR2(32000);
loopCount NUMBER;
diff_file_handle UTL_FILE.FILE_TYPE;
fix_file_handle UTL_FILE.FILE_TYPE;
no_of_diff NUMBER;
whereclause VARCHAR2(5000) := ' WHERE repconflict_tmstp > sysdate - 8 ';
FUNCTION getkeys(sname VARCHAR2, oname VARCHAR2) RETURN VARCHAR2 IS
CURSOR pkeys_cur(sname VARCHAR2, oname VARCHAR2) IS
SELECT column_name
FROM dba_constraints a, dba_cons_columns b
WHERE a.constraint_name=b.constraint_name AND
a.owner = b.owner AND
a.owner = sname AND
a.constraint_type='P' AND
a.table_name=oname
ORDER BY position;
CURSOR rep_key_cols_cur(psname VARCHAR2, poname VARCHAR2) IS
SELECT col
FROM dba_repkey_columns
WHERE sname = psname AND
oname = poname;
key_str VARCHAR2(500);
BEGIN
FOR i IN pkeys_cur(sname,oname) LOOP
IF (key_str IS NULL) THEN
key_str := i.column_name;
ELSE
key_str := key_str||','||i.column_name;
END IF;
END LOOP;
IF (key_str IS NULL) THEN
FOR i IN rep_key_cols_cur(sname,oname) LOOP
IF (key_str IS NULL) THEN
key_str := i.col;
ELSE
key_str := key_str||','||i.col;
END IF;
END LOOP;
END IF;
RETURN(key_str);
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('ERROR IN getkeys : '||TO_CHAR(SQLCODE));
RAISE;
END;
BEGIN
/*
IF (file_name IS NULL) THEN
file_name := group_name||'.diff';
END IF;
IF (fix_file_name IS NULL) THEN
fix_file_name := group_name||'.fix';
END IF;
*/
init_file(dir_name,NVL(file_name,groupname||'.diff'));
init_file(dir_name,NVL(file_name,groupname||'.fix'));
diff_file_handle := open_file(dir_name,NVL(file_name,groupname||'.diff'),FALSE);
fix_file_handle := open_file(dir_name,NVL(fix_file_name,groupname||'.fix'),FALSE);
FOR i in links_cur(groupname) LOOP
dblinks(idx) := i.dblink;
idx := idx +1 ;
END LOOP;
idx := 1;
FOR i in objects_cur(groupname) LOOP
schemas(idx) := i.sname;
objects(idx) := i.oname;
idx := idx + 1;
END LOOP;

FOR tabidx IN 1..schemas.COUNT LOOP
IF (individual_files) THEN
diff_file_handle := open_file(dir_name,objects(tabidx)||'.diff',FALSE);
fix_file_handle := open_file(dir_name,objects(tabidx)||'.fix',FALSE);
END IF;
key_cols := getkeys(schemas(tabidx),objects(tabidx));
IF (skip_columns IS NOT NULL) THEN
all_cols := ','||getcols(schemas(tabidx),objects(tabidx));
get_table_for_str(skip_cols_tab,skip_columns);
FOR i IN 1..skip_cols_tab.COUNT LOOP
--dbms_output.put_line('to be replaced='||'<'||all_cols||'>');
--dbms_output.put_line('Replace='||','||skip_cols_tab(i)||',');
all_cols := REPLACE(all_cols,','||skip_cols_tab(i)||',',',');
END LOOP;
all_cols := SUBSTR(all_cols,2,length(all_cols)-2);
ELSE
all_cols := '*';
END IF;
dbms_output.put_line('all_cols='||substr(all_cols,1,200));
IF (dblinks.COUNT = 2) THEN
LoopCount := 1;
ELSE
LoopCount := NVL(dblinks.COUNT,1)-1;
END IF;
FOR i IN 1..LoopCount LOOP
dbms_output.put_line('Processing '||schemas(tabidx)||'.'||objects(tabidx)||'@'||dblinks(1)||' AND '||schemas(tabidx)||'.'||objects(tabidx)||'@'||dblinks(i+1));
--no_of_diff := diff_table_internal(schemas(tabidx),objects(tabidx),dblinks(1),schemas(tabidx),objects(tabidx),dblinks(i+1),key_cols,diff_file_handle,fix_file_handle,diff_limit,whereclause,whereclause,whereclause,'*',commit_batch,timestamp_col,FALSE,NULL);
no_of_diff := diff_table_internal(schemas(tabidx),
objects(tabidx),
dblinks(1),
schemas(tabidx),
objects(tabidx),
dblinks(i+1),
key_cols,
diff_file_handle,
fix_file_handle,
diff_limit,
where_clause,
where_clause,
where_clause,
all_cols,
skip_columns,
commit_batch,
timestamp_col,
FALSE,
NULL,
compare_tmstp);
END LOOP;
IF (individual_files) THEN
UTL_FILE.FCLOSE(diff_file_handle);
UTL_FILE.FCLOSE(fix_file_handle);
END IF;
END LOOP;
IF NOT(individual_files) THEN
UTL_FILE.FCLOSE(diff_file_handle);
UTL_FILE.FCLOSE(fix_file_handle);
END IF;
EXCEPTION
WHEN OTHERS THEN
RAISE;
END;



Tom Kyte
November 22, 2006 - 3:54 pm UTC

amazing that you would actually post hundreds and hundreds of lines of CODE

and believe that I'd just debug it.

amazing.


anyway, problem in first function, you get flamed for this one:
</code> http://asktom.oracle.com/Misc/ouch-that-hurts.html <code>

you have the equivalent of a when others then null there,

EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('ERROR in opening file '||dir_name||','||file_name);
DBMS_OUTPUT.PUT_LINE('ERROR in opening file:'||TO_CHAR(SQLCODE));
DBMS_OUTPUT.PUT_LINE('ERROR in opening file:'||SQLERRM);
END;

WHY WHY WHY WHY WHY do you do that, what is the POINT, the PURPOSE, the "logic".


this (from the very end) is funny too:

EXCEPTION
WHEN OTHERS THEN
RAISE;
END;

what is the point of that - just to PURPOSELY HIDE the actual line number the error happened on??

sorry - when I see a major mistake in the very beginning and ending of a source code file, one that is HUNDREDS of lines long.....

Just how much do you expect Tom to do??

Jay Arnonld, November 24, 2006 - 2:03 am UTC

Following on from Amits post above.

Could you please help me with the following

1. I need to provide my company with a new mine production system - could you write, debug and provide ongoing support
2. My middle daughter needs to learn piano
3. My youngest son wants to be a professional soccer player
4. My wife wants another baby
5. I want a new car

If you could please drop everything and help me out!!

When Other (Does Work)

A reader, September 19, 2013 - 5:42 pm UTC

To properly use the "Others Exceptions" is to trap the condition in-line with the code throwing the exception using:

FUNCTION TRCD_CHASE_UP

begin

v_ord_nbr := '1000455321';
v_sub_ord_nbr := '001';

open trcd_chase_x (v_ord_nbr,v_sub_ord_nbr);

exception
when others then
prog_location := '100';
prog_sqlcode := sqlcode;
prog_exception := 'E001: trcd_chase Cursor - Open Error';
RAISE invalid_condition;
end;

---------------------------------------------------------
Loop (with Fetch Cursor) and Other logic removed...
---------------------------------------------------------
Then you have an exception handler at the end of the function displays where the exception cane from in terms of a location in your code:

EXCEPTION

when invalid_subprogram then
--rollback;
display_message('Aborting Execution...');

when invalid_condition then
--rollback;
--parm_data.status := '1'; -- 0 = Good, 1 = Bad
--parm_data.message := '(Message) '||prog_exception;
display_message('Invalid Condition Detected... ');
display_message('Prog Exception = '||prog_exception);
display_message('Prog Location = '||prog_location);
display_message('Prog Sqlcode = '||prog_sqlcode);


RETURN parm_chase_data;

END TRCD_CHASE_UP;

Thus your code has built-in exception blocks that assist in debugging your code (or live system failure). You MUST use the RAISE command (ie. Raise Invalid_Condition) to make this work properly with the "Master" Exception Handler at the end of the function

More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library