How do I loop within a select statement anspass in parameters? [message #6875] |
Fri, 09 May 2003 10:23 |
Jennifer
Messages: 20 Registered: September 1999
|
Junior Member |
|
|
Hi! I want to update my records to null (which is currently working) and then delete the row of records where all the fields except the primary key are null. How do I go about coding it? Please help... Thanks
Below is my code. The logic is there but I just don;t know how to should code it. The first part was workign but I do not know how to go about looping the record for the second part which begins with 'for v_tables in c_tables loop'. How do I move the next data in the cursor like a recordset using .next??
create or replace procedure scheduledelete is
cursor c_tables is
Select distinct tablename from retentionschedule where disposalaction = 'Delete' and disposaldate < sysdate;
cursor c_tempo is
select * from retentionschedule where disposalaction = 'Delete' and disposaldate < sysdate;
begin
for v_tempo in c_tempo loop
execute immediate
'update CRM.' || v_tempo.tablename || ' set ' || v_tempo.fieldname || ' = null' || ' where customerid = :customerid' using
v_tempo.customerid;
execute immediate
'delete from retentionschedule' || ' where id = :id' || ' and customerid = :customerid' || ' and disposaldate = :
disposaldate' || ' and tablename = :tablename' || ' and fieldname = :fieldname' || ' and disposalaction = :disposalaction'
using v_tempo.id, v_tempo.customerid, v_tempo.disposaldate, v_tempo.tablename, v_tempo.fieldname, v_tempo.disposalaction;
end loop;
commit;
for v_tables in c_tables loop
cursor c_columnname is
'Select COLUMN_NAME from USER_TAB_COLUMNS where TABLE_NAME = ' || v_tables.tablename || ' and column_NAME != (Select
column_name from user_cons_columns where CONSTRAINT_NAME = (
Select constraint_name from user_constraints where constraint_type ='P' and table_name =' || v_tables.tablename ||' ))' using
v_tables.tablename;
count number
statement char
begin
count=0
for v_columnname in c_columnname loop
if count=0
statement = 'delete from v_tables.tablename where' || v_columnname.next || 'is null'
count=1
else
statement = statement || ' and ' || v_columnname.next|| 'is null';
end loop;
commit;
end scheduledelete;
/
|
|
|
Re: How do I loop within a select statement anspass in parameters? [message #6879 is a reply to message #6875] |
Fri, 09 May 2003 12:19 |
Todd Barry
Messages: 4819 Registered: August 2001
|
Senior Member |
|
|
First off, you do not need to use dynamic SQL for that delete in the first cursor loop. There is nothing dynamic about it - just use static SQL and the variable values. If you are deleting the row you just processed, that would probably be better done in one statement outside the loop, but I'll leave that alone for now.
As far as evaluating the non-PK columns for a null value, I would make it much simpler by just testing columns that could have NULL values. This will eliminate the PK by definition and any other columns that are NOT NULL. No point in testing those.
I also wouldn't commit partway through the proc. Either everything happens successfully or nothing happens.
So, it might look something like:
create or replace procedure scheduledelete
is
cursor c_tempo is
select *
from retentionschedule
where disposalaction = 'Delete'
and disposaldate < sysdate;
cursor c_tables is
select distinct tablename
from retentionschedule
where disposalaction = 'Delete'
and disposaldate < sysdate;
v_sql varchar2(4000);
begin
for v_tempo in c_tempo loop
execute immediate
'update CRM.' || v_tempo.tablename ||
' set ' || v_tempo.fieldname || ' = null' ||
' where customerid = :customerid' using v_tempo.customerid;
delete
from retentionschedule
where id = v_tempo.id
and customerid = v_tempo.customerid
and disposaldate = v_tempo.disposaldate
and tablename = v_tempo.tablename
and fieldname = v_tempo.fieldname
and disposalaction = v_tempo.disposalaction;
end loop;
for v_tables in c_tables loop
v_sql := null;
for c in (select column_name
from user_tab_columns
where table_name = v_tables.tablename
and nullable = 'Y') loop
v_sql := v_sql || ' and ' || c.column_name || ' is null';
end loop;
if v_sql is not null then
execute immediate
'delete from ' || v_tables.tablename ||
' where ' || ltrim(v_sql, ' and ');
end if;
end loop;
commit;
end scheduledelete;
/
|
|
|
Re: How do I loop within a select statement anspass in parameters? [message #6885 is a reply to message #6879] |
Fri, 09 May 2003 21:19 |
Jennifer
Messages: 20 Registered: September 1999
|
Junior Member |
|
|
Hi Todd, thanks for replying the code u have provided my is workgin but I have left out a "CRM." in the select statement "select column_name from user_tab_columns where .......and nullable = 'Y'". The procedure should be:
create or replace procedure scheduledelete is
cursor c_tempo is
select * from retentionschedule where disposalaction = 'Delete' and disposaldate <= sysdate;
cursor c_tables is
select distinct tablename
from retentionschedule where disposalaction = 'Delete' and disposaldate <= sysdate;
v_sql varchar2(4000);
begin
for v_tempo in c_tempo loop
execute immediate
'update CRM.' || v_tempo.tablename || ' set ' || v_tempo.fieldname || ' = null' || ' where customerid = :customerid' using v_tempo.customerid;
delete from retentionschedule where id = v_tempo.id and customerid = v_tempo.customerid and disposaldate = v_tempo.disposaldate and tablename = v_tempo.tablename and fieldname = v_tempo.fieldname and disposalaction = v_tempo.disposalaction;
end loop;
for v_tables in c_tables loop
v_sql := null;
for c in (select column_name from CRM.user_tab_columns where table_name = v_tables.tablename and nullable = 'Y') loop
v_sql := v_sql || ' and ' || c.column_name || ' is null';
end loop;
insert into temp values (v_sql);
if v_sql is not null then
execute immediate
'delete from CRM.' || v_tables.tablename || ' where ' || ltrim(v_sql, ' and ');
end if;
end loop;
commit;
end scheduledelete;
/
The problem now is ,is there anyway a person with "user" role execute the same data as in "select column_name from CRM.user_tab_columns where table_name = v_tables.tablename and nullable = 'Y'" ? because I cannot access it just using "CRM." as "user_tab_columns" belongs to the datadict (not sure about this)
Sorry for the trouble...
|
|
|
Re: How do I loop within a select statement anspass in parameters? [message #6886 is a reply to message #6879] |
Fri, 09 May 2003 21:50 |
Jennifer
Messages: 20 Registered: September 1999
|
Junior Member |
|
|
Hi! I have also tried to replace the select statement to "select column_name from DBA_tab_columns where owner = 'CRM' and table_name = v_tables.tablename and nullable = 'Y'" and have also grant the user a DBA role but I have encountered the followign error:
20/10 PL/SQL: SQL Statement ignored
20/34 PL/SQL: ORA-00942: table or view does not exist
21/1 PL/SQL: Statement ignored
21/30 PLS-00364: loop index variable 'C' use is invalid
I have tried executing this select statement by replacing the variable "v_tables.tablename " with a value and was able to execute successfully. What is wrong?
|
|
|
|
|
Re: How do I loop within a select statement anspass in parameters? [message #6905 is a reply to message #6903] |
Sat, 10 May 2003 20:27 |
Jennifer
Messages: 20 Registered: September 1999
|
Junior Member |
|
|
Hi! I was so relieved that I could get a reply even on weekends! Phew!!
I have already changed it to all_tab_columns but the last delete is not carried out. I suspect that it could be the single quote for v_tables.tablename that I missed out as it is a string. How do I go about adding a ' ' to the Select statement "select column_name from all_tab_columns where table_name = v_tables.tablename and nullable = 'Y' and owner = 'CRM'" as 'CRM' already has got single quote?
Thanks
|
|
|
Re: How do I loop within a select statement anspass in parameters? [message #6918 is a reply to message #6905] |
Sun, 11 May 2003 18:02 |
Todd Barry
Messages: 4819 Registered: August 2001
|
Senior Member |
|
|
Well, this isn't dynamic SQL so you don't need to worry about the single quotes as you would if it was part of another string.
You just need to modify the cursor loop as I showed in my last message - query on all_tab_columns instead of user_tab_columns and add the owner = 'CRM' part to the WHERE clause.
You may need to throw a DBMS_OUTPUT line in that loop so you can see the actual DELETE statement that is dynamically built and executed. That should narrow down why something isn't happening the way you think it should be happening...
|
|
|