IBM plsql - cursor - sql

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

Related

PL/SQL procedure not compiling

I have a PL/SQL procedure that is not compiling. The errors are:
Error(3,7): PLS-00103: Encountered the symbol "INTO" when expecting one of the following: ( begin case declare 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 The symbol "INTO" was ignored.
Error(8,1): PLS-00428: an INTO clause is expected in this SELECT statement.
My code:
CREATE OR REPLACE PROCEDURE findvisitsandlaborcosts
as
begin
select * from SI.customer;
end;
/
I have googled an online syntax checker and it says on the first line there is an error. But WHERE?!? It seems to be correct. I have googled the syntax of declaring a procedure and I have cross-checked many times. It must be something simple that I am overlooking...
in a PLSQL code, you need a placeholder to keep results of a SELECT query. Since PLSQL engine is expecting INTO clause within SELECT statement.
To begin with, you can select a set of columns and assign their values to local variables.
Your code should be like this -
CREATE OR REPLACE PROCEDURE findvisitsandlaborcosts
as
v_column1 SI.customer.column1%type;
v_column2 SI.customer.column2%type;
begin
select column1, column2 into v_column1, v_column2 from SI.customer;
end;
/
Note - you need to replace column1 and column2 with actual column names before running this code at your end.
If you want the results to get displayed on the caller of the procedure, then you would define an out parameter and print the records outside of the procedure
CREATE OR REPLACE PROCEDURE findvisitsandlaborcosts(x out sys_refcursor)
as
begin
open x for
select * from dual;
end;
/
--Note this block of code needs to be run in sqlci or sqldeveloper
define m ref cursor;
exec findvisitsandlaborcosts(:x);
print x;
Oracle 12c has support for implict return results
Have a look at this link
https://oracle-base.com/articles/12c/implicit-statement-results-12cr1

OPEN emp_refcur FOR {plsql variable} giving error

I am novice in plsql development.
I have a problem opening cursor on plsql variable (which has my dynamic SQL query). I am on ORACLE 12 i believe.
Details below:
emp_refcur SYS_REFCURSOR; -- Cursor declaration
component_sql:= 'select * from emp'; -- Base SQL
-- dynamic sql based on business logic
IF SOME_CONDITION THEN
filters:= ' where DEP IN (''ABC'',''DEF'')';
ELSE
filters:= ' where age>50';
component_sql:= component_sql||filters; -- appending filter to my base sql
OPEN emp_refcur FOR component_sql; -- opening the cursor
LOOP
FETCH emp_refcur INTO result;
EXIT WHEN emp_refcur%NOTFOUND;
dbms_output.put_line(result);
END LOOP;
CLOSE emp_refcur;
Compiling this procedure shown error at line 'OPEN emp_refcur FOR component_sql' and error are
Error(90,9): PL/SQL: Statement ignored
Error(90,29): PLS-00382: expression is of wrong type
I do not want to use bind values like
'OPEN emp_refcur FOR p_query_string USING p_deptno, p_sal;'
I have tried multiple approaches
OPEN emp_refcur FOR ''||component_sql||''; -- This approach is not causing compilation error, but running the procedure resulting
ORA-00900: invalid SQL statement
AND
OPEN emp_refcur FOR 'select * from emp'||filters; -- This is resulting the error
ORA-00900: invalid SQL statement
Not sure what i am missing here. Please help.
NOTE: Please ignore if there are any SQL query syntax errors. Because the SQL which i am printing after appending the filters is executing fine and getting results when i run separately.
I tried with your code and it has no issues. PLS-00382: expression is of wrong type --> This is a syntax error. It has nothing to do with bind variables. What is the declaration for result? I don't see in the snippet.
PLS-00382: expression is of wrong type
Cause: An expression has the wrong datatype for the context in which it was found.
Action: Change the datatype of the expression. You might want to use datatype conversion functions.
Declare
emp_refcur SYS_REFCURSOR;
filters varchar2(100);
component_sql varchar2(100);
result varchar2(20);
Begin
component_sql:= 'select 1 from dual'; -- Base SQL
-- dynamic sql based on business logic
IF 1=1 THEN
filters:= ' UNION ALL SELECT 2 from dual';
ELSE
filters:= ' where age>50';
End if;
component_sql:= component_sql||filters; -- appending filter to my base sql
OPEN emp_refcur FOR component_sql ; -- opening the cursor
LOOP
FETCH emp_refcur INTO result;
EXIT WHEN emp_refcur%NOTFOUND;
dbms_output.put_line(result);
END LOOP;
CLOSE emp_refcur;
END;

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

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;

How to create a Trigger in oracle?

I have oracle database 11gR2 and i want to create some triggers automatically with a block .
when i want to run query in below , i have an error .
My block is :
declare
tablesid number ;
tablenames varchar2(4000);
cursor c1 is
select id , title from hr.tables;
begin
open c1;
loop
fetch c1 into tablesid , tablenames;
CREATE OR REPLACE TRIGGER tablenames||'_before_insert'
before insert
on hr.tablenames
DECLARE
columnid number ;
columnval number ;
columntitle varchar(4000);
cursor c2 is
select id from hr.columns where tableid = tablesid ;
BEGIN
-- open c2 ;
for rec in c2 loop
select title into columntitle from hr.columns where id = rec.id
insert into hr.rowaction(columnid,newvalue,oldvalue,actiondate)
(
select id ,:new.columntitle,:old.columntitle,sysdate
from hr.tabletiltes
where id = rec.id
)
select title into columntitle from hr.columns where id = rec.id;
dbms_output.put_line(columntitle);
end loop;
end;
end loop ;close c1; end;
ORA-06550: line 11, column 6:
PLS-00103: Encountered the symbol "CREATE" when expecting one of the following:
( begin case declare end 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
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action :
Bind Variable "new" is NOT DECLARED
anonymous block completed
Bind Variable "new" is NOT DECLARED
anonymous block completed
Thanks
A trigger is a standalone separate piece of code that is usually considered DDL, the language that defines metadata for objects.
You cannot have a trigger declaration embedded inside a PL/SQL block. IF you need to CREATE some PL/SQL code on the fly - not a great idea - consider the DMBS_DDL.CREATE_WRAPPED procedure. You seem to have EXECUTE IMMEDIATE in mind as well. If so, have a read on this: (http://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_ddl.htm)
You should define your trigger BEFORE running your PL/SQL in other words. Make two scripts.

Oracle SQL Stored Procedure Cursor print

Ok so I am working on a homework assignment using stored procedures.
Essentially i am just trying to use a stored procedure to run a query then print the results.
Here is what i have so far.
create or replace procedure movie_actors (mtitle varchars)as
DECLARE
CURSOR c1 is SELECT "NAME",GENDER,ADDRESS FROM MOVIESTAR WHERE "NAME" in(
SELECT STARNAME FROM STARSIN WHERE MOVIETITLE=mtitle);
actor_name MOVIESTAR.NAME%TYPE;
actor_gender MOVIESTAR.NAME%TYPE;
actor_address MOVIESTAR.ADDRESS%TYPE;
BEGIN
LOOP
FETCH c1 INTO actor_name;
FETCH c1 INTO actor_gender;
FETCH c1 INTO actor_address;
EXIT WHEN c1%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(mtitle ||', '||actor_name||': '||actor_gender||', '||actor_address);
END LOOP;
END;
I am new to databases and stored procedures. I am not sure if i am really going about this the best way.
It should be pretty simple, I am not sure what I am doing wrong.
This is the compiler error i am getting.
Error(2,1): PLS-00103: Encountered the symbol "DECLARE" when expecting one of the
following: begin function pragma procedure subtype type <an identifier> <a
double-quoted delimited-identifier> current cursor delete exists prior external
language The symbol "begin" was substituted for "DECLARE" to continue.
Error(16,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
Any help would be greatly appreciated.
First, you have an invalid type:
create or replace procedure movie_actors (mtitle varchars)as
^
This should be varchar2, not varchars.
Second, you don't need the DECLARE here. The "as" kinda substitutes for it. Start your proc like this:
create or replace procedure movie_actors (mtitle varchar2)as
CURSOR c1
Finally, I strongly recommend changing this:
CURSOR c1 is SELECT "NAME",GENDER,ADDRESS FROM MOVIESTAR WHERE "NAME"
... to this (no double quotes):
CURSOR c1 is SELECT NAME,GENDER,ADDRESS FROM MOVIESTAR WHERE NAME
The double quotes will make the column name case sensitive. You're lucky in this case because the default in Oracle is uppercase, but sooner or later using double quotes like this will cause you trouble - there are plenty of StackOverflow postings from frustrated users who've lost hours or time from using double quotes when they didn't have to.