Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Creating a simple procedure in Oracle

Status
Not open for further replies.

Packermann

Programmer
May 17, 2000
15
US
I am a novice in Oracle. I need to create a procedure that inserts a value into a table, if the insert is successful, to return all the rows in that table. Particularly I am having trouble determining whether the insert is successful and I cannot use a <b>SELECT</b> without an <b>INTO</b><br>clause.<br><br>I am much more experienced in Microsoft SQLServer . This is how I would write the procedure SQLServer:<br><br><font color=red><b><br>CREATE PROCEDURE FOR sp_test<br>AS<br>INSERT INTO testtable VALUES ('test')<br>IF @@error = 0<br>&nbsp;&nbsp;SELECT * FROM testtable<br></b></font><br><br>I am actually surprised that such a simple procedure in MSS seems to be difficult in Oracle. We have a resident expert in Oracle who could not help. Could anybody out there help me?<br><br>
 
In oracle if an error occurs an exception is raised, which you may wish to trap to avoid your program exitting. If no error occurs you may simply perform the next step in your logic.<br><FONT FACE=monospace><br>create or replace procedure my_proc as<br>&nbsp;&nbsp;&nbsp;my_value&nbsp;&nbsp;varchar2(20) := null;<br>begin<br>&nbsp;&nbsp;&nbsp;insert into test_table (col1)<br>&nbsp;&nbsp;&nbsp;values ('abc');<br><br>&nbsp;&nbsp;&nbsp;for my_cursor in<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(select col1 from test_table)<br>&nbsp;&nbsp;&nbsp;loop<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;my_value := my_cursor.col1;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-- add other code ...<br>&nbsp;&nbsp;&nbsp;end loop;<br>exception<br>&nbsp;&nbsp;&nbsp;when others then null; -- error handler<br>end my_proc;<br></font><br>
 
The exception handling part is fine, but what does not work is <b>SELECT * FROM test_table</b>. This gives an error that you need to use an INTO with a SELECT. And yet the sql statement is perectly valid if not in a procedure. How do I display the contents of a table from within a procedure?
 
The short answer is you can't. A procedure runs in the RDBMS, and thus doesn't have any direct connection with a display device. All you can do is return the information retrieved to the invoking application via parameters or global variables.<br>There is a package called DBMS_OUTPUT however, which can be used to log information if certain session settings are defined (usually for debugging purposes). I'll try and get some more info on this and post it here.
 
This might be an interesting approach, it's from a Perl DBI mailing list. I've not tried it but it *should* work.<br><br>The basic idea is to fill an array with with the info you want (<FONT FACE=monospace>populate()</font>) and write a function (<FONT FACE=monospace>get_line()</font>) that returns a single element of that array each time it is called.<br><br>It should (might?) be possible to declare a cursor in the package and return data from a single row each time <FONT FACE=monospace>get_line()</font> is called. Not sure, don't know enough about what types an oracle function can return.<br><br><FONT FACE=monospace><b><br>CREATE OR REPLACE PACKAGE FOO AS TYPE varchar_array IS TABLE OF VARCHAR2(256) INDEX BY BINARY_INTEGER;<br>&nbsp;<br>&nbsp; my_array varchar_array;<br>&nbsp; current_row NUMBER:=0; <br>&nbsp;<br>&nbsp; PROCEDURE target(data OUT varchar_array);<br>&nbsp; PROCEDURE populate;<br>&nbsp; PROCEDURE get_line(data OUT VARCHAR2);<br>&nbsp;END;<br>&nbsp;/<br>&nbsp;CREATE OR REPLACE PACKAGE BODY FOO AS<br>&nbsp;<br>&nbsp; PROCEDURE target(data OUT varchar_array) IS<br>&nbsp; BEGIN<br>&nbsp; data(0):='Line 0';<br>&nbsp; data(1):='Line 1';<br>&nbsp; data(2):='Line 2';<br>&nbsp; END;<br>&nbsp; <br>&nbsp; PROCEDURE populate IS<br>&nbsp; BEGIN<br>&nbsp; target(my_array);<br>&nbsp; current_row:=0;<br>&nbsp; END;<br>&nbsp; <br>&nbsp; PROCEDURE get_line(data OUT VARCHAR2) IS<br>&nbsp; BEGIN<br>&nbsp; IF (current_row &lt;= my_array.COUNT) THEN<br>&nbsp; data:=my_array(current_row);<br>&nbsp; current_row:=current_row+1;<br>&nbsp; END IF;<br>&nbsp; END;<br>&nbsp;END;<br>/<br></font></b> <p>Mike<br><a href=mailto:Mike_Lacey@Cargill.Com>Mike_Lacey@Cargill.Com</a><br><a href= Cargill's Corporate Web Site</a><br>Please don't send me email questions without posting them in Tek-Tips as well. Better yet -- Post the question in Tek-Tips and send me a note saying "Have a look at so-and-so in the thingy forum would you?"
 
Packermann, I've put the DBMS_OUTPUT stuff in a FAQ, as it's a bit long. If you plug this in to <FONT FACE=monospace>my_proc</font> in my previous post it should meet the case if you're invoking the procedure from SQL*Plus or similar. If you're invoking it from an application you're writing, Mike's idea of returning an array (and then letting your app do the display) may suit you better.
 
We had another solution: Use Oracle's internal EXCEPTIONS table to handle this.<br><br><u>Step 1</u>: Cate your own exceptions table, say mb_exceptions:<br><FONT FACE=monospace><br>drop table mb_exceptions;<br>create table mb_exceptions(<br>&nbsp;&nbsp;&nbsp;row_id&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rowid,<br>&nbsp;&nbsp;&nbsp;owner&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;varchar2(30),<br>&nbsp;&nbsp;&nbsp;table_name varchar2(30),<br>&nbsp;&nbsp;&nbsp;constraint varchar2(30));<br></font><br>(This is taken from script $ORACLE_HOME/rdbms/admin/utlexcpt.sql)<br><br><u>Step 2</u>: Create your source table:<br><FONT FACE=monospace><br>create table t2 (c2 number);<br><br>insert into t2 values (1);<br>insert into t2 values (2);<br>insert into t2 values (100);<br>commit;<br></font><br><br><u>Step 3</u>: Create your destination table:<br><FONT FACE=monospace><br>create table t1 (c1 number);<br></font><br><br><u>Step 4</u>: Insert from source to destination<br>(NOTE: Make sure to disable the constraints (if any) that would cause the violation.&nbsp;&nbsp;None here yet.)<br><br><FONT FACE=monospace><br>insert into t1 select * from t2;<br></font><br>Nothing bad yet.<br><br><u>Step 5</u>: Now, enable the constraint to check the violation.&nbsp;&nbsp;Here assume the constraint is column C1 must be &lt;10.<br><FONT FACE=monospace><br>alter table t1 add constraints ck_t1 check (c1 &lt;10)<br>&nbsp;&nbsp;exceptions into mb_exceptions;<br></font><br><br>When enabling this constraints, Oracle creates a record in the exception table for every record in T1 which fails the constraint.&nbsp;&nbsp;Note that it does not move the bad records out of T1 and the constraints still not enabled yet.<br><br><u>Step 6</u>: All your bad records are now in table mb_exceptions. Just display it:<br><FONT FACE=monospace><br>prompt Table t1:<br>select rowid, c1&nbsp;&nbsp;from t1;<br><br>prompt Table mb_exceptions:<br>select * from mb_exceptions;<br></font><br><br>Their results are:<br><FONT FACE=monospace><br>Table t1:<br>ROWID&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C1<br>------------------ ----------<br>AAQVUAACUAAAPYbAAA&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1<br>AAQVUAACUAAAPYbAAB&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2<br><font color=red>AAQVUAACUAAAPYbAAC</font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;100<br></font><br><br>Table mb_exceptions: <br><FONT FACE=monospace><br>ROW_ID&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OWNER&nbsp;&nbsp;&nbsp;TABLE_NAME&nbsp;&nbsp;&nbsp;CONSTRAINT<br>------------------ ------- ------------ ------------<br><font color=red>AAQVUAACUAAAPYbAAC</font> MDBUI&nbsp;&nbsp;&nbsp;T1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CK_T1<br></font><br><br>Here you see the rowid of the bad record.&nbsp;&nbsp;You can now issue a delete statement based on this rowid to delete this offending record.&nbsp;&nbsp;Or you may want to save it in some other tables for further analysis, such as display these bad records:<br><FONT FACE=monospace><br>select&nbsp;&nbsp;t1.*<br>from t1, mb_exceptions e<br>where e.row_id = t1.rowid;<br></font><br>Its results are:<br><FONT FACE=monospace><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C1<br>----------<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;100<br></font><br>
 
Isn't there a dbms_utility.write_file procedure that could be used? I haven't used it in years, but that may be a better solution (if I got the name wrong, pardon).
 
Yes, both the dbms_output print or using exception seems to work.<br><br>Thanks guys <p>Paul<br><a href=mailto:packermann@niku.com>packermann@niku.com</a><br><a href= > </a><br>
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top