Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ORACLE Batching DDL statements within a Execute Immediate

I'm trying to run multiple ddl statements within one Execute Immediate statement. i thought this would be pretty straight forward but it seems i'm mistaken.

The idea is this:

declare v_cnt number; 

begin 

select count(*) into v_cnt from all_tables where table_name='TABLE1' and owner = 'AMS'; 

if v_cnt = 0 then 

execute immediate 'CREATE TABLE TABLE1(VALUE VARCHAR2(50) NOT NULL)  ALTER TABLE TABLE1 ADD (MYVAL2 NVARCHAR2(10))'; 

end if; 

end;

however this results in an error

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

Each of the statements within the batch run fine if i execute them by themselves. and if i take this statement and execute it, it will run fine (with the ; between the 2 statements). If i remove the ; between statements i get a different error about invalid option

the plan is that i'll be able to build a table, export the table schema for this table including all it's alter statements, and then run the batch against another system as part of an install/update process.

So, how do i batch these DDL statements within a single execute immediate? Or is there a better way to do what i'm needing?

I'm a bit of a Oracle newb, i must admit. Thank you all for your patience.

like image 682
Beta033 Avatar asked Aug 06 '09 21:08

Beta033


People also ask

Can we combine multiple DDL statements in a single statement?

Create multiple tables in a single transaction in Oracle As we can see in this tip SQL Server allows us to include multiple DDL commands in a single transaction in contrast to Oracle. The latter commits transactions when a DDL command is issued, so it is not possible to combine DDL statements in one transaction.

What happens to the current transaction If a DDL statement is executed?

If a DDL statement is executed, the current transaction will be committed and ended. All the database changes made in the current transaction will become permanent. This is called an implicit commit by a DDL statement.

Can we use execute immediate in Oracle function?

The EXECUTE IMMEDIATE statement executes a dynamic SQL statement or anonymous PL/SQL block. You can use it to issue SQL statements that cannot be represented directly in PL/SQL, or to build up statements where you do not know all the table names, WHERE clauses, and so on in advance.

Is execute immediate in Oracle Autocommit?

Commit is not required after every EXECUTE IMMEDIATE. Certain statements do NOT require a commit; for example, if you truncate a table with TRUNCATE.


2 Answers

The semicolon is not part of Oracle's SQL syntax. SQL*Plus and other client side tools use semicolon to signal the end of a SQL Statement, but the server doesn't see it.

We can force SQL*Plus to pass the semicolon to the DB:

SQL> set sqlterminator off
SQL> select * from user_tables;
  2  /
select * from user_tables;
                         *
ERROR at line 1:
ORA-00911: invalid character

If i take this statement and execute it, it will run fine (with the ; between the 2 statements) The client tool you are using, breaks it into two calls to the DB.

So, I don't think it is possible to pass multiple statements inside an execute immediate.

I suppose one could call execute immediate with a string containing an anonymous PL/SQL block, with individual calls to execute immediate inside it ... and I don't know what the point of doing that would be. ;)

like image 128
Shannon Severance Avatar answered Oct 06 '22 21:10

Shannon Severance


Why do you need a single EXECUTE IMMEDIATE call? Surely just do it as 2 calls?

Bear in mind that each DDL statement contains an implicit COMMIT, so there's no concurency benefit to doing it as a single call.

Also, why not just set up the table correctly in the first call? You could do...

CREATE TABLE TABLE1(VALUE VARCHAR2(50) NOT NULL, MYVAL2 NVARCHAR2(10))

...instead of needing 2 calls.

Also, have you looked at DBMS_METADATA... it can generate DDL for objects such as tables for you.

like image 2
cagcowboy Avatar answered Oct 06 '22 20:10

cagcowboy