Why the Oracle procedure not compiling? - oracle

CREATE OR REPLACE PROCEDURE ResetVersionNumberValue IS
sql_stmt VARCHAR2(2000);
BEGIN
FOR sql_stmt IN (select 'update '|| table_name ||
' set version = 0'
from user_tables
where table_name like 'MY_%')
LOOP
EXECUTE IMMEDIATE sql_stmt;
END LOOP;
COMMIT;
END;
Why the about procedure is not compiling? Its giving error saying
Error(8,26): PLS-00382: expression is of wrong type
How to resolve this?

Two things:
You need to remember that when iterating a cursor it returns a ROW, not a VALUE, and
The SELECT in the cursor needs to give a name to the value in the row being generated by the cursor.
Try:
CREATE OR REPLACE PROCEDURE ResetVersionNumberValue IS
BEGIN
FOR aRow IN (select 'update '|| table_name ||
' set version = 0' AS SQL_STMT
from user_tables
where table_name like 'MY_%')
LOOP
EXECUTE IMMEDIATE aRow.SQL_STMT;
END LOOP;
COMMIT;
END;
Share and enjoy.

CREATE OR REPLACE PROCEDURE ResetVersionNumberValue IS
BEGIN
FOR sql_stmt IN (
select 'update '|| table_name || ' set version = 0' as x
from user_tables
where table_name like 'MY_%')
LOOP
EXECUTE IMMEDIATE sql_stmt.x;
END LOOP;
COMMIT;
END;

Related

Oracle creating a dynamic plsql command

I'm trying to put together a procedure, which counts the rows for each PARTITION in a table but I'm getting a syntax error:
Errors: PROCEDURE COUNT_PARTITION
Line/Col: 14/31 PLS-00103: Encountered the symbol "(" when expecting one of the following:
I know this isn't the most efficient way and I can use the num_rows column along with gathering statistics to achieve the same results.
Below is my test CASE. I know the problem is with the construction of the 'cmd' call but I can't seem to get it to work. Any help would be greatly appreciated.
CREATE OR REPLACE PROCEDURE cmd(p_cmd varchar2)
authid current_user
is
BEGIN
dbms_output.put_line(p_cmd);
execute immediate p_cmd;
END;
/
CREATE OR REPLACE PROCEDURE
count_partition(
p_tab varchar2
) authid current_user
is
v_cnt integer;
BEGIN
for cur_rec in (select table_name, partition_name,
partition_position
FROM user_tab_partitions where table_name = p_tab order by partition_position) loop
cmd ('select count(*) /*+ parallel(a,8) */
from ' ||p_tab|| 'PARTITION ' ('||cur_rec.partition_name||')' INTO v_cnt);
DBMS_OUTPUT.PUT_LINE(cur_rec.table_name || ' ' || cur_rec.partition_name || ' ' || v_cnt || ' rows');
end loop;
END;
Created a procedure and wrapper
CREATE OR REPLACE PROCEDURE
count_partition(
p_tab varchar2
) authid current_user
is
sql_stmt varchar2(1024);
row_count number;
cursor get_tab is
select table_name,
partition_name
from user_tab_partitions
where table_name=p_tab;
BEGIN
for get_tab_rec in get_tab loop
BEGIN
sql_stmt := 'select count(*) /*+ parallel(a,4) */ from ' ||get_tab_rec.table_name||' partition ( '||get_tab_rec.partition_name||' )';
--dbms_output.put_line(sql_stmt);
EXECUTE IMMEDIATE sql_stmt INTO row_count;
dbms_output.put_line('Table '||rpad(get_tab_rec.table_name
||'('||get_tab_rec.partition_name||')',50)
||' '||TO_CHAR(row_count)||' rows.');
exception when others then
dbms_output.put_line
('Error counting rows for table '||get_tab_rec.table_name);
END;
END LOOP;
END;
/
BEGIN
FOR cur_r IN(
SELECT TABLE_NAME FROM USER_PART_TABLES
)
LOOP
--DBMS_OUTPUT.put_line('Table '|| cur_r.table_name);
count_partition (cur_r.table_name);
END LOOP;
END;
~~

execute immediate using cursor

I've number of tables that i want to drop some columns and add some another columns again. (oracle database)
All of tables are empty.
does it work??
DECLARE
CURSOR cursor_name
IS
SELECT TABLE_NAME
FROM SYS.ALL_TABLES
WHERE OWNER = 'username';
TN NVARCHAR2 (30);
TABLE_COUNT NUMBER (3);
TCDROP NVARCHAR2 (1000);
TCADD NVARCHAR2 (1000);
BEGIN
SELECT COUNT (1)
INTO TABLE_COUNT
FROM SYS.ALL_TABLES
WHERE OWNER = 'username';
OPEN cursor_name;
FOR i IN 1 .. TABLE_COUNT
LOOP
FETCH cursor_name INTO TN;
TCDROP := 'ALTER TABLE ' || TN || ' DROP (*columns list*);';
EXECUTE IMMEDIATE TCDROP;
TCADD :=
'ALTER TABLE ' || TN || ' ADD (*columns and datatype list*);';
EXECUTE IMMEDIATE TCADD;
EXIT WHEN cursor_name%NOTFOUND;
END LOOP;
CLOSE cursor_name;
END;
/
Yes, this will certainly work. I'd recommend to put in the owner/schema of the tables, though. Besides, it is unusual or unsafe to query the number of tables and the loop through the list. I'd put it in a simple for loop:
DECLARE
stmt VARCHAR2(1000);
BEGIN
FOR t IN (SELECT table_name FROM all_tables WHERE owner='XYZ') LOOP
stmt := 'ALTER TABLE '||owner||'.'||table_name||' DROP (*columns list*);';
DBMS_OUTPUT.PUT_LINE(stmt);
EXECUTE IMMEDIATE (stmt);
stmt:= 'ALTER TABLE '||owner||'.'||table_name||' ADD (*columns and datatype list*);';
DBMS_OUTPUT.PUT_LINE(stmt);
EXECUTE IMMEDIATE (stmt);
END LOOP;
END;
/

Drop Index , then Insert Statement after that Create back Index, does not work in Procedure

create or replace PROCEDURE INSSEL_TBL_TEST AS
BEGIN
DECLARE
TBL varchar2(50):= 'ESSCSHSTMTBPTEST2';
tblNm varchar2(50);
CURSOR tableIndexList IS
(select ES_INDEX_NM,ES_TBL_NM,ES_CRT_INDEX_STMT,ES_DROP_INDEX_STMT FROM ESSP.ESSINDEXCONF WHERE ES_TBL_NM = TBL);
BEGIN
FOR drpInd in tableIndexList LOOP
EXECUTE IMMEDIATE 'drpInd.ES_DROP_INDEX_STMT';
COMMIT;
END LOOP;
execute immediate ('insert into ESSPREP.' ||UPPER(TBL)|| ' select * from ESSP.' ||UPPER(TBL)|| '#ESSPREPLINKESSP');
FOR drpInd in tableIndexList Loop
execute immediate 'drpInd.ES_CRT_INDEX_STMT';
COMMIT;
END LOOP;
END;
END;
above is my procedure to drop index before insert statement, after that create back the index.But it not work,anyone can help ?
Line
EXECUTE IMMEDIATE 'drpInd.ES_DROP_INDEX_STMT';
is wrong. You're trying to use value from cursor but as a fact you're using string literal. To fix this error just remove quotes:
EXECUTE IMMEDIATE drpInd.ES_DROP_INDEX_STMT;
Also, as #XING said, commit is superfluous here.
Your syntax is not correct. See below:
create or replace PROCEDURE INSSEL_TBL_TEST
AS
TBL varchar2(50):= 'ESSCSHSTMTBPTEST2';
tblNm varchar2(50);
CURSOR tableIndexList IS
(select ES_INDEX_NM,ES_TBL_NM,ES_CRT_INDEX_STMT,ES_DROP_INDEX_STMT FROM ESSP.ESSINDEXCONF WHERE ES_TBL_NM = TBL);
BEGIN
FOR drpInd in tableIndexList LOOP
EXECUTE IMMEDIATE drpInd.ES_DROP_INDEX_STMT;
--COMMIT;-- DROP is a DDL hence no need for COMMIT
END LOOP;
execute immediate 'insert into ESSPREP.' ||UPPER(TBL)|| ' select * from ESSP.' ||UPPER(TBL)|| '#ESSPREPLINKESSP';
FOR drpInd in tableIndexList Loop
execute immediate drpInd.ES_CRT_INDEX_STMT;
END LOOP;
END;

anonymous block in 11g

I need a help on this.
I am trying to create a pl/sql anonymous block and when I run that it shows its completed but it don't run the code. It should give me an error saying name is already used by an existing object. Can someone help me on this.
I am actually creating procedures but just trying this code as a sample.
DECLARE
V_REF_TBL VARCHAR2(100);
V_SQL LONG;
begin
V_REF_TBL :='My_TABLE';
v_SQL :='truncate table '||V_REF_TBL ;
EXECUTE IMMEDIATE V_SQL;
EXECUTE IMMEDIATE 'CREATE TABLE '|| V_REF_TBL ||' parallel 9 nologging pctfree 0 as
select * from dual';
End;
Possibly you're looking for this:
<<my_block>>
Declare
table_name varchar2(30);
counter number;
Begin
table_name := 'my_table';
select count(*)
into counter
from user_tables
where table_name = Upper(Trim(my_block.table_name)) and
dropped = 'NO';
if counter = 0
then
execute immediate 'create table '||table_name||' as ... etc';
else
execute immediate 'truncate table '||table_name;
execute immediate 'insert into '||table_name' select ... etc';
end if;
end my_block;

how to make a loop for all columns of a table?

I have a table EMPLOYEES, i need to make a loop, on every step of the loop I use dbms_output.put_line(column_name)
How can I make this?
Just found this solution
begin
for rec in (SELECT column_name
FROM all_tab_columns
WHERE owner = 'HR'
AND table_name = 'EMPLOYEES')
loop
dbms_output.put_line(rec.column_name);
end loop;
end;
Try to use cursor as below:
set serveroutput on;
declare
var_col1 varchar2(30) ;
num_col2 number ;
CURSOR cur
is
select var_col ,num_col
from table
where <conditions>;
begin
open cur;
fetch cur into var_col1,num_col2;
LOOP
fetch cur into var_col1,num_col2;
EXIT WHEN cur%NOTFOUND;
dbms_output.put_line( var_col1||' '||num_col2);
END LOOP;
close cur;
end;
here is another solution:
set serveroutput on;
begin
FOR cur in ( select var_col ,num_col from table where <conditions>)
LOOP
dbms_output.put_line(cur.var_col||' = '||cur.num_col);
END LOOP;
end;
Of course You can rewrite this SELECT example with WHERE after table_name. I dont compiled this code but I thinks its OK. Change ID_Employee and Name for your atributes
CREATE OR REPLACE PROCEDURE AAA_TEST
IS
BEGIN
DECLARE
v_id NUMBER :=0;
v_name VARCHAR2(25);
CURSOR cursorMails IS
SELECT Id_Employee,Name FROM EMPLOYEES;
BEGIN
OPEN cursorMails;
LOOP
FETCH cursorMails INTO v_id, v_name;
DBMS_OUTPUT.PUT_LINE('Number of Employee: ' || v_id || ' Name Employee: ' || v_name);
EXIT WHEN cursorMails%NOTFOUND;
END LOOP;
CLOSE cursorMails;
END;
END;
/

Resources