How to return code from anonymous PLSQL block to ksh variable - plsql

Here is a ksh :
$ORACLE_HOME/bin/sqlplus id/psw#$ORACLE_SID #$P_SQL/mysql.sql $1
return_code=$?
echo return_code
Here is the sql :
set serverout on
var error number
...
declare
error number(1) := 0;
begin
.......
exception
when too_many_rows then
error := 2;
end;
/
exit
How to pass the PLSQL error value to SQLPLUS variable and then the SqlPlus variable to the ksh variable return_code.
Thank you

It is possible to pass a SQL error code from a PL/SQL script to the shell.
However, the shell will perform modulo 256 on the SQL error number. If you needed a specific number, you could use a user defined error with a custom error number.
SET SERVEROUT ON
WHENEVER SQLERROR EXIT SQL.SQLCODE;
DECLARE
l_result VARCHAR2(1);
BEGIN
SELECT result
INTO l_result
FROM (SELECT 'A' result
FROM dual
UNION
SELECT 'B' result
FROM dual);
EXCEPTION
WHEN too_many_rows THEN
Raise_application_error(-20226, 'Custom error ' || MOD(20226, 256) || ' for too many rows');
END;
/
exit

Related

Calling a stored procedure with CLOB output

I am trying to use the CLOB datatype as the output parameter in my stored procedure because its resultset exceeds the storage capacity of a var datatype.
How do I execute the procedure? Below are the commands I had run to execute.
I tried assigning the resultset to the the CLOB variable using the INTO query as shown in the query.
var cl CLOB;
EXECUTE procedure_name(:cl);
print cl;
How do i declare the binding variable because if you look at the first command, I am first initializing cl as var I am not able to initialize it as CLOB as it is giving out an error.
This is a sample of my procedure. The actual query in the procedure is 700 lines long.
CREATE OR REPLACE PROCEDURE procedure_name (cl OUT CLOB)
IS
BEGIN OPEN cl FOR
SELECT * FROM .....
statement 1
.
.
.
.
.
statement n
INTO cl
FROM
statement 1
.
.
.
statement n
EXCEPTION
WHEN
OTHERS THEN
DECLARE
err_num NUMBER := SQLCODE;
err_msg VARCHAR2(512) := SQLERRM;
error_id_pk NUMBER;
error_dt DATE;
BEGIN
SELECT (REGEXP_REPLACE(CURRENT_TIMESTAMP, '[^0-9]+', ''))INTO error_id_pk FROM DUAL;
SELECT SYSDATE INTO error_dt FROM DUAL;
INSERT INTO ODS_CONTROL.ERROR_DETAILS(ERROR_ID, ERROR_CODE, ERROR_DATE, PROCEDURE_NAME, ERROR_MSG)
VALUES ( error_id_pk,
err_num,
error_dt,
'PRC_FLEXI_CARD',
err_msg
);
END;
END;
Error message:
Error starting at line : 2 in command -
EXECUTE procedure_name( :clb )
Error report -
ORA-06550: line 1, column 7:
PLS-00905: object procedure_name is invalid
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
[TL;DR] VAR is a keyword for declaring a variable and is not a data type; your actual error is due to using invalid syntax when you tried to define your procedure and it has not compiled.
VAR is short for VARIABLE and defines a PL/SQL bind variable.
This declaration has the syntax:
VAR[IABLE] [variable [type] ]
where type represents one of the following:
NUMBER
CHAR
CHAR (n [CHAR | BYTE])
NCHAR
NCHAR (n)
VARCHAR2 (n [CHAR | BYTE])
NVARCHAR2 (n)
BLOB
BFILE
CLOB
NCLOB
REFCURSOR
BINARY_FLOAT
BINARY_DOUBLE
So with:
var cl CLOB;
you are declaring a variable using the VAR keyword and the variable is named cl and has the type CLOB.
Also, your CREATE PROCEDURE statement has a syntax error as you cannot have the single quotes around the procedure name. For example:
CREATE PROCEDURE procedure_name (clb OUT CLOB)
IS
BEGIN
clb := 'test';
END;
/
Then:
VAR cl CLOB;
EXECUTE procedure_name( :cl );
PRINT cl;
Outputs:
test
Updated:
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE ERROR_DETAILS(
ERROR_ID NUMBER,
ERROR_CODE NUMBER,
ERROR_DATE DATE,
PROCEDURE_NAME VARCHAR2(30),
ERROR_MSG VARCHAR2(512)
)
/
CREATE PROCEDURE procedure_name (cl OUT CLOB)
IS
BEGIN
SELECT DUMMY
INTO cl
FROM dual
WHERE ROWNUM = 1;
EXCEPTION
WHEN
OTHERS THEN
DECLARE
err_num NUMBER := SQLCODE;
err_msg VARCHAR2(512) := SQLERRM;
BEGIN
INSERT INTO /* ODS_CONTROL. */ ERROR_DETAILS(
ERROR_ID,
ERROR_CODE,
ERROR_DATE,
PROCEDURE_NAME,
ERROR_MSG
) VALUES (
TO_NUMBER( TO_CHAR( CURRENT_TIMESTAMP, 'YYYYMMDDHH24MISSFF9' ) ),
err_num,
SYSDATE,
'PRC_FLEXI_CARD',
err_msg
);
END;
END;
/
Query 1:
SELECT * FROM USER_ERRORS
Results:
No rows selected

Returning table results from a dynamic PL/SQL query

Trying to dynamically generate and execute a PL/SQL statement. It doesn't return results, but executing okay. What I am trying is to get the table name from the schema in first statement (got it right!), and append that to a select statement, and then execute it to return the table results.
DECLARE
LATEST_TABLE VARCHAR2(256);
PostalCode ADM.POSTAL_CODE_201801%ROWTYPE;
BEGIN
SELECT TO_CHAR(max(table_name)) INTO LATEST_TABLE FROM all_tables WHERE owner = 'ADM' AND table_name LIKE 'POSTAL_CODE_%';
LATEST_TABLE := 'begin Select POSTALCODE,LONGITUDE,LATITUDE,MUNICIPALITY_FULL_NAME,LOCAL_NAME,SZONE_NAME,ZONE_NAME,RHA_CODE,RHA_NAME,URBAN,ZONE_RURAL from ADM.'||LATEST_TABLE||' ;end;';
execute immediate LATEST_TABLE into PostalCode;
Exception
When others then
Null;
END;
Why am I not getting any results? Adding
dbms_output.put_line(PostalCode.LONGITUDE || PostalCode.LATITUDE); after execute immediate is also not generating results!
I see a couple of issues here; your code is something like:
declare
vSQL varchar2(1000);
vTabName varchar2(30);
vResult number;
begin
select table_name into vTabName from user_tables;
vSQL := 'begin select a from ' || vTabName || '; end;';
execute immediate vSQL into vResult;
dbms_output.put_line('REsult: ' || vResult);
exception
when others then
null
end;
If you run this, you see nothing, because the dynamic part gives error, but the (dangerous) exception handling hides it; if you would edit the null; into something like
dbms_output.put_line('Error: ' || sqlerrm);
you would get:
Error: ORA-06550: line 1, column 7:
PLS-00428: an INTO clause is expected in this SELECT statement
In fact you dynamic code is like
begin select a from someTable; end;
and this gives error.
A way to do what you need could be:
...
vSQL := 'select a from ' || vTabName;
execute immediate vSQL into vResult;
...

Oracle APEX: Execute immediate on collection

I have the following code:
declare
y pls_integer := 0;
v_msg varchar2(4000);
plsql varchar(4000);
begin
if not apex_collection.collection_exists(p_collection_name=>'P16_COLLECTION') then
wwv_flow.debug('No Apex collection found!');
else
for x in (select * from apex_collections where collection_name = 'P16_COLLECTION' and seq_id > 1 order by seq_id)
loop
y := y+1;
FOR i IN 1..25
LOOP
plsql := 'begin apex_collection.update_member_attribute (p_collection_name=> ''P16_COLLECTION'', p_seq=>' || TO_CHAR(x.seq_id) || ',p_attr_number =>' || TO_CHAR(i) || ',p_attr_value=>wwv_flow.g_f' || TO_CHAR(i, 'FM00') || '(' || TO_CHAR(y) || ')); end;';
wwv_flow.debug(plsql);
EXECUTE IMMEDIATE plsql;
END LOOP;
end loop;
end if;
exception when others then
v_msg := ''||sqlerrm;
wwv_flow.debug('ERR: '||v_msg);
end;
This code is very similar to the one proposed here, but I loop through 25 columns. The issue with Oracle Apex is the max number of chars PL/SQL is allowed to have, so I am unable to just write 25 update_member_attribute - calls.
But instead of a it excecuting I get an error no data found.
I triple checked that the collection P16_COLLECTION exists.
The issue with Oracle Apex is the max number of chars PL/SQL is allowed to have
I'm not sure I understood this statement. It is PL/SQL you use. You declared a local PLSQL variable as VARCHAR2(4000). Why didn't you specify its max allowed size, 32767? Would that help?
Furthermore, saying that you got NO-DATA-FOUND exception: are you sure that this piece of code raised it? Because, there's no SELECT statement in there ... the one you used in a cursor FOR loop can't raise NO-DATA-FOUND; UPDATE either. Therefore, it must be something else, I presume.
Enable DEBUG, run the page and - when you get the error - view debug results and locate the culprit.

Warning: Trigger created with compilation errors?

I am trying to implement Trigger that raises an User Defined Error Message and does not allow the update and Insert operation in the database.I am new to pl/sql i refereed some code from the internet and try to implement.My code is running is fine as i can not update/insert into database but still i am unable to get my user defined message and also i am getting this warning.
Warning: Trigger created with compilation errors ?
This is the table :
Name Null? Type
----------------------------------------- -------- ----------------------------
ID NUMBER(5)
NAME VARCHAR2(20)
SALARY NUMBER(10)
DEPOT_ADDRESS VARCHAR2(15)
here is my code :
create or replace trigger cleaner_before_update_insert
for update or insert on cleaner
compound trigger
count binary_integer;
before statement is
begin
count:=0;
end before statement;
after each row is
begin
count :=count +1;
end after each row;
after statement is
begin
if count > 0 then
raise_application_error( -20001,'Update/insert operation can not be completed ');
end if;
end after statement;
end cleaner_before_update;
/
can anyone help me figure out what is the problem here and way to fix it.
thanks in advance.
Even after compilation of the code it is giving me this error.
ORA-06512: at "SYSTEM.CLEANER_BEFORE_UPDATE_INSERT", line 18
ORA-04088: error during execution of trigger
'SYSTEM.CLEANER_BEFORE_UPDATE_INSERT'
There are couple of problems with your TRIGGER block.
The name of the Trigger cleaner_before_update_insert does not match with the cleaner_before_update after the final end statement.
COUNT is an SQL keyword which is not allowed to be used as a variable in PL/SQL.You would receive the error - Error(10,11): PLS-00204: function or pseudo-column 'COUNT' may be used inside a SQL statement only
So, here is the modified code.
CREATE OR REPLACE TRIGGER cleaner_before_update_insert FOR UPDATE OR
INSERT ON cleaner compound TRIGGER
v_count binary_integer;
before STATEMENT
IS
BEGIN
v_count:=0;
END before STATEMENT;
AFTER EACH row
IS
BEGIN
v_count :=v_count +1;
END AFTER EACH row;
AFTER STATEMENT
IS
BEGIN
IF v_count > 0 THEN
raise_application_error( -20001,'Update/insert operation can not be completed ');
END IF;
END AFTER STATEMENT;
END cleaner_before_update_insert;
/

wrong number or types of arguments in call to my procedure

hi I wrote this code to create a procedure to return a Boolean value based on the if conditions but when I execute it I got this error:
ORA-06550: line 1, column 7:
PLS-00306: wrong number or types of arguments in call to 'DDPAY_SP'
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
here is my procedure
create or replace procedure DDPAY_SP (
donor_id dd_donor.iddonor%type,
pldgstatus out dd_pledge.idstatus%type,
monthplan out dd_pledge.paymonths%type,
ret out boolean)
IS
begin
select idstatus, paymonths into
pldgstatus, monthplan from dd_pledge
where iddonor = donor_id ;
if (pldgstatus = 10 AND monthplan >0)
then ret:= true;
else
ret:= false;
end if;
end;
and this how I execute it
EXECUTE DDPAY_SP (308);
I didn't put much talk I hope it's clear enough for you
I read online it recommends me to check the naming also the data type which I did but nothing change
any ideas
If you don't need the second and third arguments you could declare those as variables in the procedure instead of arguments, as follows:
CREATE OR REPLACE PROCEDURE DDPAY_SP(DONOR_ID IN DD_DONOR.IDDONOR%TYPE,
RET OUT BOOLEAN)
IS
nPayment_count NUMBER;
BEGIN
SELECT COUNT(*)
INTO nPayment_count
FROM DD_PLEDGE p
WHERE p.IDDONOR = DONOR_ID AND
p.IDSTATUS = 10 AND
p.PAYMONTHS > 0;
IF nPayment_count > 0 THEN
RET := TRUE;
END IF;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('DD_PAY - exception: ' || SQLCODE || ' : ' || SQLERRM);
RAISE;
END DDPAY_SP;
I've included an example of an EXCEPTION handler at the end of DD_PAY. It's always a good idea to include at least this minimal handler so that in the event an exception occurs you'll get some indication of where the problem lies.
Because this procedure returns a BOOLEAN value, and BOOLEANs cannot (to the best of my knowledge) be used from SQL*Plus, you'll have to invoke it from a PL/SQL block, as follows:
DECLARE
bRetval BOOLEAN;
BEGIN
DD_PAY(308, bRetval);
DBMS_OUTPUT.PUT_LINE('Returned value is ' ||
CASE bRetval
WHEN TRUE THEN 'TRUE'
ELSE 'FALSE'
END);
END;
Give that a try.
EDIT: rewrote procedure based on further information from later comments.
Share and enjoy.

Resources