How to remove error code and print only message | PLSQL - plsql

I have to print only error message and remove code number
BEGIN
IF :MY_TEXT is null THEN
raise_application_error(-20001,'Text field cannot be empty')
END IF;
Exception
when others then
:MSG := replace(SQLERRM,'^ORA-+:','');
END;
Expected output :
Text filed cannot be empty

You need to use something like this SUBSTR(MSG, INSTR(MSG, ':', 1, 1)+2 )
DECLARE
MY_TEXT VARCHAR2(100);
MSG VARCHAR2(100);
BEGIN
IF MY_TEXT is null THEN
raise_application_error(-20001,'Text field cannot be empty');
END IF;
Exception
when others then
MSG := SQLERRM ;
dbms_output.put_line( SUBSTR(MSG, INSTR(MSG, ':', 1, 1)+2 ) );
END;
/

You could also just change your REPLACE call to a REGEXP_REPLACE as it appears you were trying to use a regular expression to match the error:
:MSG := REGEXP_REPLACE(SQLERRM,'^ORA-[0-9]+: ', NULL);
Match a pattern of 'ORA-' at the start of the line, followed by 1 or digits, then a colon followed by a space and replace with NULL.
Note technically the ', NULL' is not needed in this call but including makes it clear to future maintainers what the intention is here and I would argue would be best practice.

Related

PLS-00653 Error on an empty line (Aggregate/table functions are not allowed in PL/SQL scope)

I'm trying to run a PL/SQL Script I made but I'm getting an error:
PLS-00653: aggregate/table functions are not allowed in PL/SQL scope
The problem here is not the error in itself but the line where it's being thrown from.
Here's my PL/SQL block which throws this error:
DECLARE
TYPE l_code_arr_typ IS VARRAY(3) OF VARCHAR2(100);
l_code_arr l_code_arr_typ;
l_objet objet_interface_pkg.objet_interface_typ;
l_resultat CLOB;
l_valeur valeur_pkg.valeur_typ;
l_liens lien_objet_interface_pkg.lien_objet_interface_tab;
l_rows NUMBER;
BEGIN
l_code_arr := l_code_arr_typ('champ.fonctions.dossier.particulier',
'champ.fonctions.region.admin',
'champ.fonctions.ministere.organisme');
l_resultat := '{';
FOR l_idx IN 1 .. l_code_arr.count LOOP
l_objet := objet_interface_pkg.obtenir_fnc(p_code => l_code_arr(l_idx),
p_acron_sys => :acronyme);
l_resultat := l_resultat || '"' || l_objet.code || '":[';
l_liens := lien_objet_interface_pkg.obtenir_par_objet_fnc(p_id_objet => l_objet.id_obj);
FOR l_lien IN (SELECT * FROM TABLE(l_liens)) LOOP
l_valeur := valeur_pkg.obtenir_fnc(p_id => l_lien.id_valeur);
l_resultat := l_resultat || '"' || l_valeur.valeur || '"';
FOR l_enfant IN (SELECT *
FROM TABLE(valeur_pkg.obtenir_enfants_fnc(p_id_parent => l_lien.id_valeur,
p_code => l_valeur.valeur))) LOOP
l_resultat := l_resultat || ',"' || l_enfant.valeur || '"';
END LOOP;
END LOOP;
l_resultat := l_resultat || '],';
END LOOP;
<<<<<<<<<< ERROR THROWN HERE (EMPTY LINE)
l_resultat := substr(l_resultat, 1, length(l_resultat) - 1) || '}';
dbms_output.put_line(l_resultat);
END;
The error throws on 34:17 (line:column) which is the fourth line from the end of the code block. As you can see the real problem is that this line is an empty line. Moreover, none of the lines near that empty line contains a call to an aggregate function. So where's the aggregate/table function's call located?
I'm wondering if the problem really comes from my code or if my PL/SQL Developer is broken.
I hope someone can help me...
I found the solution!
The problem is that the function lien_objet_interface_pkg.obtenir_par_objet is PIPELINED and a pipelined return cannot be stored in a variable.
So these 2 lines...
l_liens := lien_objet_interface_pkg.obtenir_par_objet_fnc(p_id_objet => l_objet.id_obj);
FOR l_lien IN (SELECT * FROM TABLE(l_liens)) LOOP
...need to be merge into one single line like so:
FOR l_lien IN (SELECT * FROM TABLE(lien_objet_interface_pkg.obtenir_par_objet_fnc(p_id_objet => l_objet.id_obj))) LOOP
However, I still don't know why PL\SQL Developer said my error comes from line 34 and It'll probably remain a mystery. If anyone have answer to this mystery, please feel free to let me know.

PLS-00103: Encountered the symbol "G_OUTPUT" when expecting one of the following: :=

--script2.sql
--Krishan Billa
ACCEPT p_make PROMPT 'ENTER MAKE OF THE CAR';
ACCEPT p_model PROMPT 'ENTER MODEL OF THE CAR';
ACCEPT p_year PROMPT 'ENTER YEAR OF THE CAR';
ACCEPT p_color PROMPT 'ENTER COLOR OF THE CAR';
VARIABLE g_output VARCHAR2(500);
DECLARE
CURSOR allprospects
IS
SELECT b.cname,
TRIM(b.cstreet),
TRIM(b.ccity),
TRIM(b.cprov),
TRIM(b.cpostal)
FROM s9.prospect a
INNER JOIN s9.customer b
ON(a.cname =b.cname)
WHERE UPPER(a.make)=UPPER('&p_make')
AND UPPER(a.model) =UPPER('&p_model')
AND a.cyear ='&p_year'
AND UPPER(a.color) =UPPER('&p_color');
BEGIN
:g_output := '&p_make'||CHR(10);
FOR v_prospect IN allprospects LOOP
:g_output := :g_output||'test';
--:g_output := :g_output || v_prospect.cname || CHR(10)|| v_prospect.ccity || CHR(10);
--:g_output := :g_output || v_prospect.ccity ||','|| v_prospect.cprov || ' ' || v_prospect.cpostal || CHR(10);
END LOOP;
END;
PRINT g_output;
--select make,model,cyear,color,count(*)from s9.prospect group by model,make,cyear,color;
--desc s9.prospect;
--desc s9.customer;
--JAGUAR XL 2016 RED 2
Please see the error below when i run this code. It looks pretty fine to me. Can anyone please help? Thankyou
ORA-06550: line 24, column 7:
PLS-00103: Encountered the symbol "G_OUTPUT" when expecting one of the following: := . ( # % ; 06550. 00000 - "line %s, column %s:\n%s"
You're missing the terminator SQLPlus is looking at the end of the plsql block. So the line "print g_output" is included in the block sent to the plsql "compiler". The compiler doesn't know what to do with it, and is not expecting it. That is the error. Try:
END;
/
PRINT g_output;

PLS-00103: Encountered the symbol "IF" when expecting one of the following

Below is my function in Oracle:
create or replace
FUNCTION CALCULATEINT
( DebtNo IN VARCHAR2
, JFlag IN VARCHAR2
, FloatingInterestRate IN NUMBER
) RETURN NUMBER IS
AccInt NUMERIC(17,8):=0;
BEGIN
DECLARE
PrincipalDue NUMERIC(11,2);
InterestDue NUMERIC(17,8);
IF (JFlag IN ('B', 'C', 'Y')) THEN
BEGIN
SELECT
DEF_JUDG_PRINC_DUE ,
DEF_JUDG_PRINC_RATE
bulk collect into PrincipalDue ,InterestDue
FROM
DANT
WHERE
AND DE_NO = DebtNo ;
END;
END IF;
RETURN AccInt;
END;
I am getting errors below:
1.PLS-00103: Encountered the symbol "IF" when expecting one of the following: begin function pragma procedure subtype type current cursor delete exists prior The symbol "begin" was substituted for "IF" to continue.
2.PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following: ( begin case declare end exception exit for goto if loop mod null pragma raise return select update while with << continue close current delete fetch lock insert open rollback savepoint set sql execute commit forall merge pipe purge
create or replace
FUNCTION CALCULATEINT
( DebtNo IN VARCHAR2
, JFlag IN VARCHAR2
, FloatingInterestRate IN NUMBER
) RETURN NUMBER IS
AccInt NUMERIC(17,8):=0;
BEGIN
DECLARE
PrincipalDue NUMERIC(11,2);
InterestDue NUMERIC(17,8);
BEGIN
IF (JFlag IN ('B', 'C', 'Y')) THEN
SELECT
DEF_JUDG_PRINC_DUE ,
DEF_JUDG_PRINC_RATE
bulk collect into PrincipalDue ,InterestDue
FROM
DANT
WHERE
AND DE_NO = DebtNo ;
END IF;
END;
RETURN AccInt;
END;
Move the if statement from before the anonymous begin to after the begin.
I am certain that is the error.
Correspondingly you also need to move the end statement after the end if block.
Hope this helps.

Assign value to a field of rowtype where `field name` is a string

I want to assign a value to a rowtype's field but I don't know how to do it.
Suppose that I have a table X inside my database.
Suppose also that I have the following variables
a ( X%ROWTYPE ), representing a row of the table X
b ( VARCHAR2 ), containing a column name of the table X
c ( VARCHAR2 ), containing what I want to store inside a.b
What I want to do : something like a.b := c.
I've come up with something like this :
EXECUTE IMMEDIATE 'SELECT '|| c || ' INTO a.' || b || ' FROM DUAL';
Apparently, this isn't the right way to go. I get a ORA-0095: missing keyword error.
Can anyone help me with this ?
Here is the complete code :
DECLARE
tRow MyTable%ROWTYPE;
col_name VARCHAR(10) := 'Length';
nValue NUMBER(12,4) := 0.001;
dynamic_request VARCHAR(300);
BEGIN
dynamic_request := 'SELECT '|| nValue || ' INTO tRow.' || col_name || ' FROM DUAL';
EXECUTE IMMEDIATE dynamic_request;
END;
Ok, I solved it !
Short answer : Using a global variable does the trick
Answer Development
Let us consider two facts about dynamic PL/SQL blocks (i.e., PL/SQL blocks written as strings, to be executed trough an EXECUTE IMMEDIATE statement)
[1] There is no such thing as variable scope when you create a dynamic PLSQL block. What I mean by that is, if you do something like this :
CREATE OR REPLACE PROCEDURE DynamicVariableAssignment(
theString IN VARCHAR2
)
IS
BEGIN
EXECUTE IMMEDIATE 'BEGIN theString := ''test''; END; ';
END;
it will simply not work because the scope of theString is not transfered to the dynamic PL/SQL block. In other words, the dynamic PL/SQL block doesn't "inherit" of any variable, wherever it is executed.
[2] You might say "OK, no panic, I can give input/output arguments to my dynamic PL/SQL block, right ?". Sure you can, but guess what : you can only give SQL types as in/out ! True PL/SQL types on the other hand, such as a myTable%rowtype, are not accepted as an input for a dynamic PL/SQL block. So the answer of hmmftg won't work either :
-- I've reduced the code to the interesting part
dynamic_request := 'BEGIN :t_row.' || col_name || ':= 0.001; END;';
EXECUTE IMMEDIATE dynamic_request USING IN OUT tRow;
-- (where tRow is of type myTable%ROWTYPE)
since tRow is of MyTable%ROWTYPE, it is not a valid SQL type and is therefore not valid as an input to the dynamic PL/SQL block.
The Solution Who would have thought that global variables would come and save the day ? As we said in [1], we have no reference to any variable outside the dynamic PL/SQL block. BUT we can still access global variables defined in package headers !
Let us assume that I have a package kingPackage in which I define the following :
tempVariable myTable%ROWTYPE;
Then I can do this :
FINAL CODE (body only)
-- Copy tRow into temp variable
kingPackage.tempVariable := tRow;
-- We modify the column of the temp variable
vString := 'BEGIN kingPackage.tempVariable.' || col_val || ' := ' || TO_CHAR(vNumber) ||'; END;';
EXECUTE IMMEDIATE vString;
-- The column value has been updated \o/
tRow := kingPackage.tempVariable;
There you go, fellas !
Have a nice day
try this:
CREATE OR REPLACE PROCEDURE ROW_CHANGER(
tRow IN MyTable%ROWTYPE,
col_name IN VARCHAR,
nValue IN NUMBER)
AS
dynamic_request VARCHAR(300);
BEGIN
dynamic_request := 'BEGIN :t_row.'||COL_NAME ||':= :n_value; END;';
EXECUTE IMMEDIATE dynamic_request
USING IN OUT TROW, IN nValue;
END;
this is because in your EXECUTE IMMEDIATE the tRow MyTable%ROWTYPE is not defined,
so we defined it with using statement.

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