Error on creating stored procedure under Oracle - PLS-00103 - oracle

Im trying to create a stored procedure that calls another a number of times. This is done so by using a for each loop. All the development is under oracle sql developer Version 3.0.04.
CREATE OR REPLACE PROCEDURE Z_INBILLABILITYSERV
IS BEGIN
DECLARE
ano VARCHAR2(4);
BEGIN
select EXTRACT(YEAR FROM sysdate) into ano from dual;
FOR dat IN (SELECT * FROM Z_FECHOMES WHERE MES <=
(select EXTRACT(MONTH FROM sysdate) from dual )and ANO = ano)
LOOP
call z_insertbillability(dat.periodo_inicio,dat.periodo_fim,
dat.ano,dat.mes);
END LOOP;
END;
END;
Im having the following error:
Error(9,12): PLS-00103: Encountered the symbol "Z_INSERTBILLABILITY" when expecting one of the following: := . ( # % ; The symbol ":=" was substituted for "Z_INSERTBILLABILITY" to continue.
If anyone have an idea or a tip i would be glad to now and would appreciate a lot.

You do not need the word call; just do:
LOOP
z_insertbillability(dat.periodo_inicio,dat.periodo_fim,
dat.ano,dat.mes);
END LOOP;
The error message is perhaps a bit unhelpful, but it's to be trying to show all the ways it could try to interpret the word call, since it doesn't recognise it as a keyword. And showing what it would expect to see next for each: as a variable name (which would be followed by := for assignment; or a schema name (which would be followed by .); or a function/procedure name (which would be followed by ( for the parameter list), etc.

Related

PLS-00103: Encountered the symbol "IS" when expecting one of the following: := . ( # % ; not null range default character

I am facing this error:
LINE/COL ERROR
-------- -----------------------------------------------------------------
4/11 PLS-00103: Encountered the symbol "IS" when expecting one of the
following:
:= . ( # % ; not null range default character
My package is:
CREATE OR REPLACE PACKAGE BODY EMP_PK AS
PROCEDURE INSERT_TR(EMPNO EMP_20171250.EMPNO%TYPE,ENAME EMP_20171250.ENAME%TYPE,SAL EMP_20171250.SAL%TYPE) IS
INSERT_ERROR EXCEPTION;
CRUSOR C1 IS INSERT INTO EMP_20171250(EMPNO,ENAME,SAL) VALUES(EMPNO,ENAME,SAL);
BEGIN
IF(C1%FOUND) THEN
DBMS_OUTPUT.PUT_LINE('RECORD INSERTED');
ELSE
RAISE INSERT_ERROR;
END IF;
EXCEPTION
WHEN INSERT_ERROR THEN
DBMS_OUTPUT.PUT_LINE('ERROR WHILE RECORD INSERTION');
END INSERT_TR;
END EMP_PK;
it is not CRUSOR but CURSOR
cursor can't contain INSERT statement; it is a SELECT
you are checking whether cursor returned something, but - you never opened it nor fetched from it so it is pretty much useless
insert_error looks like there was an error while inserting a row, but - you are actually raising it if cursor didn't return anything
Basically, you don't need a cursor at all. Such a procedure would do:
PROCEDURE insert_tr (p_empno emp_20171250.empno%TYPE,
p_ename emp_20171250.ename%TYPE,
p_sal emp_20171250.sal%TYPE)
IS
BEGIN
INSERT INTO emp_20171250 (empno, ename, sal)
VALUES (p_empno, p_ename, p_sal);
END insert_tr;
If insert fails, Oracle will raise an exception anyway so - yes, you can handle it/them if you want.
Also, it is good to distinguish parameter names from column names; for example, precede their names with a p_ (as I did).

getting error while compiling the stored procedure

I am writing this below stored procedure but i am also getting the exception while compiling the procedure in oracle, below is the procedure
CREATE OR REPLACE PACKAGE BODY TEST_TABLE AS
PROCEDURE TEST_TABLE
--This procedure will delete partitions for the following tables:
--TEST_TABLE
BEGIN
FOR cc IN
(
SELECT partition_name, high_value
FROM user_tab_partitions
WHERE table_name = 'TEST_TABLE'
)
LOOP
EXECUTE IMMEDIATE 'BEGIN
IF sysdate >= ADD_MONTHS(' || cc.high_value || ', 3) THEN
EXECUTE IMMEDIATE
''ALTER TABLE TEST_TABLE DROP PARTITION ' || cc.partition_name || '
'';
END IF;
dbms_output.put_line('drop partition completed');
END;';
END LOOP;
exception
when others then
dbms_output.put_line(SQLERRM);
END;
END;
/
and the exception that I am getting it while compiling is Please advise how to overcome from this.
Error(7,1): PLS-00103: Encountered the symbol "BEGIN" when expecting one of the following: ( ; is with authid as cluster order using external deterministic parallel_enable pipelined result_cache The symbol ";" was substituted for "BEGIN" to continue.
Error(22,25): PLS-00103: Encountered the symbol "DROP" when expecting one of the following: * & = - + ; < / > at in is mod remainder not rem return returning <an exponent (**)> <> or != or ~= >= <= <> and or like like2 like4 likec between into using || bulk member submultiset
You need to make correct quotation as below( and one more is keyword just after PROCEDURE TEST_TABLE "thanks to Alex who make me awaken" ) :
CREATE OR REPLACE PACKAGE BODY PKG_TEST_TABLE IS
PROCEDURE TEST_TABLE IS
--This procedure will delete partitions for the following tables:
--TEST_TABLE
BEGIN
FOR cc IN
(
SELECT partition_name, high_value
FROM user_tab_partitions
WHERE table_name = 'TEST_TABLE'
)
LOOP
BEGIN
IF sysdate >= ADD_MONTHS(cc.high_value, 3) THEN
EXECUTE IMMEDIATE
'ALTER TABLE TEST_TABLE DROP PARTITION ' || cc.partition_name;
Dbms_Output.Put_Line('Dropping partition is completed.');
END IF;
END;
END LOOP;
EXCEPTION WHEN Others THEN Dbms_Output.Put_Line( SQLERRM );
END TEST_TABLE;
END PKG_TEST_TABLE;
/
As a little suggestion use a different name for package than procedure such as PKG_TEST_TABLE against confusion.
Edit : of course you need to create a specification part for a package before the body part of the package :
CREATE OR REPLACE PACKAGE PKG_TEST_TABLE IS
PROCEDURE TEST_TABLE;
END PKG_TEST_TABLE;
/
The first error message tells you something is missing before BEGIN, and even mentions the two possible options in the 'when expecting' list. You need to change it to:
PROCEDURE TEST_TABLE IS
-- ^^
Or you can use AS instead of IS if you prefer...
The second error is because you have a string literal embedded in your dynamic SQL and you haven't escaped the single quotes, though you have elsewhere:
...
dbms_output.put_line(''drop partition completed'');
-- ^ ^
END;';
You could use the alternative quoting mechanism instead.
I'm not sure why you're doing two levels of dynamic SQL; you can do the dbms_output() and evaluate cc.high_value statically, and decide whether to make the alter call, with only that part dynamic (as #BarbarosĂ–zhan has shown, so I wont repeat that!). Or do the high-value check within the cursor query.
I am still getting exception Error(1,14): PLS-00304: cannot compile body of 'TEST_TABLE' without its specification
If you want a package then you have to create its specification before you try to create its body:
CREATE OR REPLACE PACKAGE TEST_TABLE AS
PROCEDURE TEST_TABLE;
END TEST_TABLE;
/
CREATE OR REPLACE PACKAGE BODY TEST_TABLE AS
PROCEDURE TEST_TABLE IS
BEGIN
FOR cc IN
...
LOOP
...
END LOOP;
END TEST_TABLE; -- end of procedure
END TEST_TABLE; -- end of package
/
Having the package name the same as a procedure within it is a bit odd and confusing.
But maybe you didn't actually want a package at all, and were trying to create a standalone procedure, in which case just remove the package-body part:
CREATE OR REPLACE PROCEDURE TEST_TABLE AS
BEGIN
FOR cc IN
...
LOOP
...
END LOOP;
END TEST_TABLE; -- end of procedure
/
Read more.
I would strongly suggest you get rid of the exception handler, and I've left that out of those outlines - you should let any exception flow back to the caller. You don't know that whoever calls this will even have output enabled, so might well not even see the message you're printing instead. Only ever catch exceptions you can handle and need to handle at that point.

Oracle PL/SQL - parameterizing SAMPLE clause in SELECT statement

I have a Oracle related question. I would like to select a random sample out of a view or table in such a way that the SAMPLE clause is parameterized.
Given the following table.
CREATE TABLE FOO AS
(SELECT LEVEL AS ID
FROM DUAL
CONNECT BY LEVEL < 101
);
The following construct works, using a literal parameter in the SAMPLE clause.
SELECT ID FROM FOO SAMPLE (15); -- this will get a 15% sample
However,
DECLARE
N NUMBER := 50;
BEGIN
FOR r IN
( SELECT ID FROM FOO SAMPLE (N) -- <<< this won't work
)
LOOP
DBMS_OUTPUT.PUT_LINE( r.ID );
END LOOP;
END;
This block blows up when we put a parameter in the SAMPLE clause. It compiles and works if we put it a literal.
But if it is a variable, I get the following:
ORA-06550: line 5, column 33:
PL/SQL: ORA-00933: SQL command not properly ended
Any ideas? I'm racking by brains where the syntax gets broken.
The syntax does not allow a variable there.
One workaround would be to construct the SELECT statement dynamically. For example:
declare
l_rc sys_refcursor;
n number := 5;
begin
-- replace "mtl_system_items" with your table...
open l_rc FOR 'select count(*) from mtl_system_items sample (' || n || ')';
-- replace call to RETURN_RESULT with whatever processing you want
DBMS_SQL.RETURN_RESULT(l_rc);
end;

Determining call hierarchy of PL/SQL procedure

I am working on some old PL/SQL code and I want to display the call hierarchy like I would have for Eclipse and Java code.
For instance, if I have the following code:
create or replace package body pkgA as
procedure foobar is begin
lambda(1);
end;
procedure lambda(a NUMBER) is begin
pkgB.test();
end;
end pkgA;
/
create or replace package body pkgB as
procedure test is begin
select 1 from dual;
end;
end pkgB;
/
I'd like to have this tree:
pkgB.test
pkgA.lambda
pkgA.foobar
Note: I am using Toad 9, but I did not see such feature (well, unless I need to look for to something like the referential tree for foreign keys).
Beside, I'm looking more for a static analysis than a dynamic, or something implying that I execute the code.
I think the better package procedure to call for this is: dbms_utility.format_error_backtrace
So you'd use DBMS_OUTPUT.PUT_LINE(dbms_utility.format_error_backtrace);
I put those in my exception handler for testing all the time (to the point where I have a code template that drops it in). I also output the instruction:
So it returns results like this:
EXCEPTION IN aeo_misc_tools.cursor_to_listV2 - -900: ORA-00900: invalid SQL statement
EXCEPTION IN my test script - -900: ORA-00900: invalid SQL statement
Error stack at top level:
ORA-06512: at "AEO.AEO_MISC_TOOLS", line 805
ORA-06512: at line 8
It won't format the error in a tree format, as you specified, but it gets the job done so you can find the error on the correct line.
You can use the called hierarchy of Visual-Expert, this tools analyse the PL code and show you the call function
It might not be the best solution, but I have figured out by using PL/Scope recursively. Hope it can help anyone in need. :)
create or replace procedure getAllChildCall ( definitionName in char, packageName in char, callLevel in number )
as
begin
for rec in (
with package_tree as (
select * from all_identifiers
where object_name = packageName and object_type = 'PACKAGE BODY'
)
select distinct
name, signature, type, line,
usage, usage_id, usage_context_id
from package_tree
start with (name = definitionName and usage = 'DEFINITION')
connect by prior usage_id = usage_context_id
) loop
if rec.usage = 'CALL' and rec.name not in (
'DEBUG', 'SQLERRM', 'COMMITRECORD', 'ISNOTZERO', 'NVL', 'TRUNC', 'ROUND') then
dbms_output.put_line(LPAD(' ', 2*callLevel, ' ') || rec.name);
getallchildcall(rec.name, packageName, callLevel+1);
end if;
end loop;
end;
/
set serveroutput on
declare
callLevel number;
begin
callLevel := 1;
dbms_output.put_line('start traverse the package child call graph...');
getAllChildCall(upper('YOUR_PROCEDURE_NAME'), upper('YOUR_PACKAGE_NAME'), callLevel);
end;

ORA-00923: FROM keyword not found where expected error in oracle

I have following Store procedure in Oracle 11g. I am passing the table name as parameter through ASP.net using c#. But while running the application i am getting the error "ORA-00923: FROM keyword not found where expected error in oracle".
PROCEDURE "ARCHIVE_FILTERDATA" ( ITYPE IN VARCHAR2, itableName IN VARCHAR2, cur_archive OUT sys_refcursor ) AS
stmt clob;
endstmt clob;
BEGIN
IF ITYPE='Week'
THEN stmt := 'DELETE FROM '|| itableName ||' WHERE CREATEDATE < (SELECT DATE_ADD(CURDATE(), INTERVAL , - 1, WEEK))';
EXECUTE IMMEDIATE stmt;
END IF;
END;
So anybody have a solution please let me know ASAP. Thanks in Advance
You have three errors in your DELETE statement:
there is no date_add() function in Oracle (See the manual for a list of available functions)
there is no curdate() function in Oracle (See the manual for a list of available functions)
The sub-query is totally unnecessary. Plus: a select requires a from clause.
Putting it all together, your delete should look like this:
stmt := 'DELETE FROM '|| itableName ||' WHERE CREATEDATE < sysdate - interval ''1'' week';
(Note the duplicated single quotes inside the string literal).
Be aware that Oracle's DATE datatype always contains a time part. So sysdate - interval '1' week will return the date one week ago a the "current time". If you mean to include the complete day last week, you need to "remove" the time part by using trunc: trunc(sysdate) - interval '1' week.
You inner query will look alike:-
SELECT DATE_ADD(CURDATE(), INTERVAL , - 1, WEEK) FROM DUAL;
So plz correct your query.

Resources