Skip to Main Content

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, Adil.

Asked: March 04, 2008 - 8:20 am UTC

Last updated: October 01, 2018 - 2:41 am UTC

Version: Oracle 9.0.1.1

Viewed 10K+ times! This question is

You Asked

Hi Tom ,

i want ALTER TABLE by adding columns to it , if the columns already exist int the table then it doesn't add , else adds the columns .

how i can do that ?

Regards,
Adil

and Tom said...

by writing code that catches errors and does the right thing.

No, better idea - rethink this entire illogical approach. "I want to add a column, but if it already exists, skip it. Ignore the fact that the existing column with that name might be totally the wrong datatype, have the wrong constraints, whatever - we don't care"


This is so wrong. So very wrong. Please think about configuration management and manageable software...

Rating

  (9 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Write a psudo code with three input parameters...

Anupam ,USA, March 05, 2008 - 12:06 am UTC

declare
v_table_name Varchar2(31):='EMP'; -- Input table name
v_column_name varchar2(31):='ENAME'; -- Input column name
v_data_type varchar2(15):='varchar2(30)'; -- data type
v_exist number;
begin
select count(*) into v_exist from user_tab_cols where table_name=v_table_name and column_name=v_column_name;
if v_exist > 0 then
execute immediate 'Alter table '||v_column_name||' add ('||v_column_name ||' '||v_data_type||')';
end if;
end;
Tom Kyte
March 05, 2008 - 7:38 am UTC

this is so very very wrong.

and hah - umm - well, look at how wrong it is.

if v_exist > 0


if the column exists
please add it...
end if;



The code to add a column and deal with errors is trivial.

The ramifications of such code is too horrendous to deal with early in the morning, just ruins the day.


indicates zero degrees of control, no source code control - just whip it together, it'll probably work sometimes...

auto-magic DDL

Saager Mhatre, March 05, 2008 - 1:07 pm UTC

Whoa!!! Dynamic, programmatic DDL always scares me (even migrations in ActiveRecord scare me). I can't imagine why people would want to do stuff like this on a regular basis. It's a database, not a bunch of flat files!

Re-runable release code

John, March 05, 2008 - 4:47 pm UTC

I can see this can be usefull when running database releases into the database when it needs to be re-runable so that the release can be tested or additional objects added to the release. I have used a similar proc when releasing code and have not found a way of making a release proc rerunable without having these types of checks. Tom if you have a method/techneque to do this or you would do this a complely differnt way I would like to hear it
Tom Kyte
March 06, 2008 - 8:06 am UTC


for a failed upgrade - one would typically do a point in time recovery to before the upgrade in order to re-apply failed upgrade later. If your upgrade script (which frankly is a production *program*, a program, not 'just a script') is not coded to correct itself in the event of a failure, you need to restore the database back to a known point in time.

rais sheikh, March 06, 2008 - 2:36 am UTC

tom can it possible to alter table with the following he is using wrong table name.

execute immediate 'Alter table '||v_column_name||' add ('||v_column_name ||' '||v_data_type||')';


Tom Kyte
March 06, 2008 - 8:20 am UTC

He can debug his own code, I didn't even look at it once I saw the "if" statement - he has miles and miles to go before that code flies...

Re-running Scripts

A reader, March 06, 2008 - 12:34 pm UTC

Tom,

Features like 'drop table IF EXISTS' does not exists in Oracle, So, often we need to use dynamic SQL to make scripts re-executable for Test / Live deployment. As a part of enhancements and maintenance work, there are needs when we create scripts and then pass-it to support to deploy them to Test database and Live database. But, there are number of cases when the scripts might fail or should be killed in between because it is taking unexpected time.

eg. Support killed the session because the one of the script containts 'add column with default value'. It was OK on development because of small data on DEV as compare to others. So, they now re-run the deployment scripts and see lots of errors on the screen (which are not actually errors, it occurs because of re-execution.

To, avoid this, we use execute immediate like following :

SQL> host type add_col.sql
set feedback off
begin
  execute immediate('alter table emp drop column new_column');
exception when others then
  if sqlcode = -00904 then
     null;
  end if;
end;
/
set feedback on

alter table emp add new_column number(10);


SQL> @add_col.sql

Table altered.

SQL> @add_col.sql

Table altered.

SQL> @add_col.sql

Table altered.


What is your take on this?





Tom Kyte
March 07, 2008 - 5:01 pm UTC

My take is still - if someone killed a DDL script, part of an upgrade, you are doing a flashback database or a point in time recovery. You do upgrades during a maintenance window. If it doesn't work, you put it back the way it was.

But you did what I've been telling the above people to do: write code, handle errors.


and there is absolutely an "exists" check.


for x in ( select * from dual where NOT EXISTS (select null from user_tables where table_name = 'T')
loop
execute immediate...
end loop;

not too much different from

if not exists (select null from user_tables where table_name = 'T' )
then
execute....
end if;


which I suspect is what you were doing in t-sql.

When others then null...

ApexBine, March 07, 2008 - 9:56 am UTC

Dear "Reader",

what is the difference between
exception when others then
  if sqlcode = -00904 then
     null;
  end if;
end;
and
exception when others then
   null;
end;
?
Tom Kyte
March 10, 2008 - 10:23 am UTC

one of them is correct, proper, good, well written

and the other would be cause for dismissal from your job.



when others then null is a 'feature' of the language I would have removed if I could.

To : ApexBine from Frankfurt, Germany

A reader, March 07, 2008 - 10:31 am UTC

Thanks for pointing my mistake... sorry for that. the exception handling can be re-written in a "proper" way.

when others then null

A reader, March 07, 2008 - 10:46 am UTC

.. so I re-write the SQL

sql>host type add_col.sql
set serveroutput on
set feedback off
declare
  invalid_column exception;
  PRAGMA exception_init(invalid_column, -00904);
begin
  execute immediate('alter table emp drop column new_column');
exception when invalid_column then
  dbms_output.put_line('Adding column for first time');
end;
/
set feedback on

alter table emp add new_column number(10);

sql>



We actually can fast determime it with execute immediate

Mai Hoang Viet, August 22, 2018 - 4:03 am UTC

Please post this code on forum, it's my code which is fastest way to determine a field exist in a table
 Create function exist(v_table in varchar2, v_col in  varchar2) 
 Return integer is
 Res integer:= 0;
 Begin
   Begin
      Execute immediate 'select ' || v_col || ' from '|| v_table;         
      Res:=1;
      Exception when other then null;
   End;
Return (res);
End;

More to Explore

Administration

Need more information on Administration? Check out the Administrators guide for the Oracle Database