PLS-00103: Encountered the symbol "FETCH" when expecting one of the followingg - sql

Created a procedure as below :
create or replace
PROCEDURE TEST AS
BEGIN
DECLARE
c_service process_state.service%type;
c_tr_source process_state.tr_source%type;
CURSOR c_process_state is
SELECT service, tr_source FROM process_state;
OPEN c_process_state;
LOOP
FETCH c_process_state into c_service, c_tr_source;
insert into process_state_archive values (c_service, c_tr_source);
commit;
EXIT WHEN c_process_state%notfound;
END LOOP;
CLOSE c_process_state;
END TEST;
After compiling i ran into some errors:
Error(33,4): PLS-00103: Encountered the symbol "FETCH" when expecting one of the following: constant exception table long double ref char time timestamp interval date
Error(44,4): PLS-00103: Encountered the symbol "CLOSE" when expecting one of the following: end not pragma final instantiable volgorde overriding static member constructor map
Can anyone one please explain the problem? I am beginner and learning SQL.

1) You should declare cursor before BEGIN but not after and EXIST WHEN should be immediately after FETCH
create or replace
PROCEDURE TEST AS
c_service process_state.service%type;
c_tr_source process_state.tr_source%type;
CURSOR c_process_state is
SELECT service, tr_source FROM process_state;
BEGIN
OPEN c_process_state;
LOOP
FETCH c_process_state into c_service, c_tr_source;
EXIT WHEN c_process_state%notfound;
insert into process_state_archive values (c_service, c_tr_source);
commit;
END LOOP;
CLOSE c_process_state;
END TEST;
2) You task seems can be solved in one statement instead of a lot of code with cursor:
INSERT INTO process_state_archive select service, tr_source FROM process_state;

Related

IBM plsql - cursor

I am new with PLSQL (IDM db2) and I am trying to create a procedure to find and delete some admin_tasks if they exist.
Explanation:
By running the bellow query1, I can find out the list of tasks in the scheduler:
SELECT * FROM SYSTOOLS.ADMIN_TASK_LIST;
To delete the task, I can run this query2:
call sysproc.admin_task_remove('TASK_NAME', null);
So I want to create a procedure to delete all tasks with the pattern "My_Task_*".
This should delete all the tasks with that pattern and leave the other existent tasks intact. The procedure should handle cases where the admin_tasks doesn't exist, or no admin_tasks were ever created, and should run without throwing any errors.
I have researched and found out that this can be made using cursors.
Can you help me to implement this?
EDIT:
I managed to find this solution:
BEGIN
FOR v1 AS c1 CURSOR FOR
SELECT NAME
FROM SYSTOOLS.ADMIN_TASK_LIST
WHERE NAME LIKE 'My\_task\_%' ESCAPE '\'
DO
call sysproc.admin_task_remove(NAME, null);
END FOR;
END
This seems to work except if the SYSTOOLS.ADMIN_TASK_LIST was not yet defined.
If it's not defined than I get this error when I run the query: If it is not defined I get this error
: [Code: -204, SQL State: 42704]
"SYSTOOLS.ADMIN_TASK_LIST" is an undefined name.. SQLCODE=-204,
SQLSTATE=42704, DRIVER=4.25.1301
So how can I bypass this error? DOing something like first checking if SYSTOOLS.ADMIN_TASK_LIST is defined, if its defined to the above query if not do nothing.
Presuming that your client tool uses '#' as a statement delimiter.
BEGIN
FOR L1 AS
SELECT NAME
FROM SYSTOOLS.ADMIN_TASK_LIST
WHERE NAME LIKE 'My\_task\_%' ESCAPE '\'
DO
CALL ADMIN_TASK_REMOVE (L1.NAME, NULL);
END FOR;
END
Update:
With error handling for non-existing table. The error handler just "eats" the error on non-existing table use.
You must use dynamic sql for that.
BEGIN
DECLARE SQLSTATE CHAR (5);
DECLARE L_NAME VARCHAR (128);
DECLARE C1 CURSOR FOR S1;
DECLARE EXIT HANDLER FOR SQLSTATE '42704' BEGIN END;
PREPARE S1 FROM
'
SELECT NAME
FROM SYSTOOLS.ADMIN_TASK_LIST
WHERE NAME LIKE ''My\_task\_%'' ESCAPE ''\''
';
OPEN C1;
L1:
LOOP
FETCH C1 INTO L_NAME;
IF SQLSTATE = '02000' THEN LEAVE L1; END IF;
CALL ADMIN_TASK_REMOVE (L_NAME, NULL);
END LOOP L1;
CLOSE C1;
END

how to select into an array in pl/sql?

I'm trying to add some ids into an array:
CREATE OR REPLACE TYPE array_of_numbers AS VARRAY(10)OF NUMBER(10);
declare
student_ids array_of_numbers;
begin
select nrleg BULK COLLECT into student_ids from student where nrleg = 123458;
FOR i IN 1..student_ids.COUNT LOOP
DBMS_OUTPUT.PUT_LINE(student_ids(i));
END LOOP;
end;
but I get the following errors:
--------- -------------------------------------------------------------
3/1 PLS-00103: Encountered the symbol "DECLARE"
10/4 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 <an identifier> <a double-quoted delimited-identifier> <a bind variable> << continue close current delete fetch lock insert open rollback savepoint set sql execute commit forall merge pipe purge json_exists json_value json_query json_object json_array
Errors: check compiler log
Could someone explain what I did wrong?
Some DDL needs to be terminated with a /; a type can have a PL/SQL body so this is one of them. To run that all at once as a script do:
CREATE OR REPLACE TYPE array_of_numbers AS VARRAY(10)OF NUMBER(10);
/
declare
student_ids array_of_numbers;
begin
select nrleg BULK COLLECT into student_ids from student where nrleg = 123458;
FOR i IN 1..student_ids.COUNT LOOP
DBMS_OUTPUT.PUT_LINE(student_ids(i));
END LOOP;
end;
/
You don't need the semicolon on the end of the CREATE here, but it doesn't hurt; but for some other commands (including other DDL like create table) having both would cause it to try to execute the statement twice, which could cause an error.
SQL Developer won't complain about the lack of a / after the last PL/SQL block in a script, but other tools will, so it's better to always include that one too.
db<>fiddle
Incidentally, another way to see the contents of the array in SQL Developer is with a ref cursor:
var rc refcursor
declare
student_ids array_of_numbers;
begin
select nrleg BULK COLLECT into student_ids from student where nrleg = 123458;
open :rc for select * from table(student_ids);
end;
/
print rc
... but then you might as well just select directly from the table, without any PL/SQL.

Error creating trigger in Oracle PLSQL

I'm a student learning SQL in Oracle. I'm creating a trigger and within the trigger I'm calling a procedure update_price_history(item_id, NEW.price).
This is the statement I did,
CREATE OR REPLACE TRIGGER upd_hist_trg
BEFORE INSERT OR UPDATE OF price ON Item
FOR EACH ROW
BEGIN
IF :NEW.price != price THEN
update_price_history(item_id, NEW.price)
END IF;
END;
I thought I had everything correct but I'm getting an error message:
Error(3,2): PLS-00103: Encountered the symbol "END" when expecting one of the following: := . ( % ; The symbol ";" was substituted for "END" to continue.
I've been trying to figure out what I'm getting wrong and I'm not seeing what it is. Any help would be greatly appreciated.
You forgot the semicolon at the end
...
update_price_history(item_id, :NEW.price);
...
Try this :
CREATE OR REPLACE TRIGGER upd_hist_trg
BEFORE INSERT OR UPDATE OF price ON Item
FOR EACH ROW
DECLARE
item_id number;
BEGIN
IF :NEW.price != price THEN
update_price_history(item_id, :NEW.price);
END IF;
END;
you forgot : in front of new and a semicolon ; after procedure. By the way, i can't see any variable definition of item_id.

procedure using loop in oracle

I used oracle
I want to declare a procedure that allows me to make insertion in a table
I try with this code without success
CREATE OR REPLACE PROCEDURE ADDSTEP(nbrStep character varying)
is
i integer :=0;
BEGIN
FOR i IN 0..nbrStep LOOP
INSERT INTO mytabletest
VALUES (i);
END LOOP;
END;
I have this error :
PROCEDURE ADDSTEP compiled
Errors: check compiler log
There are multiple issues with your code:
nbrStep character varying
There is no such data type called "character varying" in Oracle. For string you would use VARCHAR2. However, since you want to use it later in the loop for iteration, you need it to be NUMBER.
FOR i IN 0..nbrStep LOOP
You need to iterate from 1 till the boundary.
i integer :=0;
Not needed.
Modify the procedure as:
CREATE OR REPLACE PROCEDURE ADDSTEP(nbrStep NUMBER)
is
i integer :=0;
BEGIN
FOR i IN 0..nbrStep LOOP
INSERT INTO mytabletest
VALUES (i);
END LOOP;
END;
/
Anyway, you entire procedure could be done in a single INSERT SQL. It is called row generator method.
Try,
INSERT INTO mytabletest
SELECT LEVEL FROM DUAL CONNECT BY LEVEL <= 100;
Above, in place of 100, you could use the value of your choice which is the value you are passing as parameter **nbrStep ** in the above procedure.
Strange syntax of input variables. Corrected for Oracle -
CREATE OR REPLACE PROCEDURE addstep(nbrstep IN NUMBER)
IS
BEGIN
FOR i IN 0.. nbrstep
LOOP
INSERT INTO mytabletest
VALUES (i);
END LOOP;
END;

Error creating Procedure

I'm getting some error with a proc I have created. The proc body is :-
CREATE OR REPLACE PROCEDURE suppress_termination_charge(v_curr_date IN DATE)
IS
TYPE suppress_term_cust_type IS RECORD (id NUMBER(11),pev NUMBER(11),piv NUMBER(11));
TYPE cur_suppress_term_cust IS REF CURSOR RETURN suppress_term_cust_type;
v_count NUMBER(4);
v_serv_item suppress_term_cust_type;
v_serv_itm_pev service_item.price_excluding_vat%TYPE;
v_serv_itm_piv service_item.price_including_vat%TYPE;
BEGIN
v_count:=0;
IF NULL=v_curr_date THEN
SELECT sysdate INTO v_curr_date FROM dual;
END IF;
OPEN cur_suppress_term_cust FOR
SELECT id AS id,price_excluding_vat AS pev,price_including_vat AS piv FROM service_items;
LOOP
FETCH cur_suppress_term_cust INTO v_serv_item;
EXIT WHEN cur_suppress_term_cust%NOTFOUND;
v_comment := 'Price changed from ('||v_serv_item.pev||', '||v_serv_item.piv||') to (0,0) (PEV, PIV) on '||v_curr_date||' for managed cease';
UPDATE service_items
SET price_including_vat=0, price_excluding_vat=0 , comments= v_comment
WHERE id = v_serv_item.id;
v_count:=v_count+1;
IF v_count=5000 THEN
COMMIT;
v_count:=0;
END IF;
END LOOP;
CLOSE cur_suppress_term_cust;
END;
/
The errors are as follows:-
SQL> SHOW ERROR;
Errors for PROCEDURE SUPPRESS_TERMINATION_CHARGE:
LINE/COL ERROR
-------- -----------------------------------------------------------------
19/30 PLS-00103: Encountered the symbol "IS" when expecting one of the
following:
. ( % ; for
23/2 PLS-00103: Encountered the symbol "FETCH" when expecting one of
the following:
constant exception <an identifier>
<a double-quoted delimited-identifier> table LONG_ double ref
char time timestamp interval date binary national character
nchar
LINE/COL ERROR
-------- -----------------------------------------------------------------
41/2 PLS-00103: Encountered the symbol "CLOSE" when expecting one of
the following:
end not pragma final instantiable order overriding static
member constructor map
I see errors but not the ones you reported:
SELECT sysdate INTO v_curr_date FROM dual;
v_curr_date is an input parameter and can't be used as a target of SELECT or FETCH.
OPEN cur_suppress_term_cust FOR...
FETCH cur_suppress_term_cust INTO v_serv_item;
EXIT WHEN cur_suppress_term_cust%NOTFOUND.
cur_suppress_term_cust is a TYPE, not a cursor variable.
v_comment := ...
v_comment is not declared.
Try fixing these issues and see if things improve.
Share and enjoy.