1

let's see if somebody can help me, I need to delete rows from different tables and I did think to do it using an array so i wrote this :

DECLARE
  TYPE mytype_a IS TABLE OF VARCHAR2(32) INDEX BY BINARY_INTEGER;
  mytype mytype_a;
BEGIN
  mytype(mytype.count + 1) := 'MYTABLE';

  FOR i IN 1 .. mytype.count 
    LOOP
      DELETE mytype(i) WHERE valid = 'N';
    END LOOP;
END;

Trying to run this piece of code using sqldeveloper I get the ORA-00933 command not properly ended, if I put directly the table name it works, what am I doing wrong?

Thank you.

Thank you very much guys, it works perfectly.

2 Answers 2

2

This is not the correct approach. You have to use Dynamic SQL for this -

DECLARE
type mytype_a is table of varchar2(32) index by binary_integer;
mytype mytype_a;
stmt varchar(500) := NULL;

BEGIN

mytype (mytype.count + 1) := 'MYTABLE';

for i in 1..mytype.count loop
    stmt := 'DELETE  FROM ' || mytype(i) || ' where valid =''N''';
    EXECUTE IMMEDIATE stmt;
    end loop;
END;
Sign up to request clarification or add additional context in comments.

Comments

1

You would need to use dynamic SQL, concatenating the table name from the collection into the statement, inside your loop:

execute immediate 'DELETE FROM ' || mytype(i) || ' where valid = ''N''';

Or you can put the statement into a variable so you can display it for debugging purposes, and then execute that, optionally with a bind variable for the valid value:

stmt := 'DELETE FROM ' || mytype(i) || ' where valid = :valid';
dbms_output.put_line(stmt);
execute immediate stmt using 'N';
dbms_output.put_line('Deleted ' || sql%rowcount || ' row(s)');

... which I've made also display how many rows were deleted from each table. Note though that you shoudln't rely on the caller being able to see anything printed with dbms_output - it's up to the client whether it shows it.

The whole anonymous block would then be:

DECLARE
  type mytype_a is table of varchar2(32) index by binary_integer;
  mytype mytype_a;
  stmt varchar2(4000);
BEGIN
  mytype (mytype.count + 1) := 'MYTABLE';

  for i in 1..mytype.count loop
    stmt := 'DELETE FROM ' || mytype(i) || ' where valid = :valid';
    dbms_output.put_line(stmt);
    execute immediate stmt using 'N';
    dbms_output.put_line('Deleted ' || sql%rowcount || ' row(s)');
  end loop;
END;
/

You could use a built-in collection type to simplify it even further.

db<>fiddle showing some options.


Hopefully this doesn't apply, but if you might have any tables with quoted identifiers then you would need to add quotes in the dynamic statement, e.g.:

stmt := 'DELETE FROM "' || mytype(i) || '" where valid = :valid';

... and make sure the table name values in your collection exactly match the names as they appear in the data dictionary (user_tables.table_name).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.