views:

326

answers:

1

I'm trying to build a test environment to test an app against oracle and sql server. The aim is to have the same code base for both test scenarios, the only difference should are some SQL/DDL/... statements that are stored in script files. The problem is that oracle's ODP does not support the execution of scripts but only single commands.

I found a workaround, but there is still one issue that I can't get solved:

My Drop script for oracle looks like this:

BEGIN EXECUTE IMMEDIATE 'SELECT ''DROP TABLE '' || table_name || '' CASCADE CONSTRAINTS;'' FROM  user_tables'; EXECUTE IMMEDIATE 'SELECT ''DROP SEQUENCE '' || sequence_name || '';'' FROM user_sequences;'; END[;]

The problem is the last semicolon after the END:

While the oracle database complains if I don't provide the semicolon at the end:

ORA-06550: line 1, column 208:
PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following:
; <an identifier> <a double-quoted delimited-identifier>
The symbol ";" was substituted for "end-of-file" to continue.)

I get an exception thrown by the oracle ODP .Net command object if I provide the semicolon:

ORA-00911: invalid character
ORA-06512: at line 1 

Is there a way to satisfy both, the oracle data base and ODP .Net?

+2  A: 

I think the semicolon issue may actually reside in the second execute immediate. When you're running SQL in execute immediate like this, putting a semicolon at the end of the string will cause an error.

However, this PL/SQL block won't actually do anything. Issuing selects inside a PL/SQL block without an INTO clause runs the query, but does nothing with the results. I think what you really want is something like this:

DECLARE
   cursor cur_tables is 
      select 'drop table ' || table_name || ' cascade constraints' as qry
      from user_tables;
   cursor cur_sequences is 
      select 'drop sequence ' || sequence_name as qry
      from user_sequences;
BEGIN
   for r_table in cur_tables loop
      execute immediate r_table.qry;
   end loop;
   for r_sequence in cur_sequences loop
      execute immediate r_sequence.qry;
   end loop;
END;

There's really no reason to make the selects dynamic, as they aren't changing. Your dynamic SQL is actually the drop statements that you're querying for.

Added commentary: You shouldn't need to wrap it in an execute immediate to run it from .NET. You should be able to pass the block to the database as a string without any changes.

Allan
Thanks Allan, this works fine. I just added an extra begin execute immediate '' around your code and replaced ' with '' in order to be able to execute it with ODP .NET
phatoni