303

I know the statement:

create table xyz_new as select * from xyz;

Which copies the structure and the data, but what if I just want the structure?

C R
  • 2,182
  • 5
  • 32
  • 41
Andrew
  • 12,991
  • 15
  • 55
  • 85

17 Answers17

473

Just use a where clause that won't select any rows:

create table xyz_new as select * from xyz where 1=0;

Limitations

The following things will not be copied to the new table:

  • sequences
  • triggers
  • indexes
  • some constraints may not be copied
  • materialized view logs

This also does not handle partitions


Raul Luna
  • 1,945
  • 1
  • 17
  • 26
Jim Hudson
  • 7,959
  • 2
  • 23
  • 15
  • 58
    This is a great, clean answer. Just want to remind that this will *not* include any constraints.. the new table won't even have a primary key. – JosephStyons Oct 24 '08 at 15:02
  • 20
    this will not replicate sequences or triggers either. – branchgabriel Oct 24 '08 at 17:29
  • 17
    nor will the new table have any indexes - don't get caught out trying to do a big query on the new table :-) – hamishmcn Nov 01 '08 at 18:09
  • 8
    also doesn't handle partitions. But hey. – MK. Oct 20 '11 at 14:38
  • 18
    Just an addendum - it *will* contain *some* constraints - i.e. any NOT NULL constraints will be copied. – Jeffrey Kemp Aug 29 '12 at 00:36
  • Will work for some simple cases, but for more complex situations it could come with a lot of extra overhead. Example when using tabular functions, the tabular function still need to be executed. There might be other cases where the optimizer cannot optimize the "1=0" efficiently and causes big chunks of sub-query still to execute. – YoYo Apr 09 '15 at 18:33
  • exactly what I needed – Pieter De Bie Aug 19 '15 at 12:44
  • What does `where 1=0` mean? – Dylan Czenski Jan 12 '16 at 14:14
  • @Jim I copied in some of the limitations from the comments. I'm not a dba, so possibly wrong. – jpaugh Oct 24 '16 at 16:43
  • 1
    @DylanChensky `1=0` is a boolean condition which will always evaluate to `false`. What YoYo is saying is, that sometimes the optimizer doesn't realize this (due to surrounding expressions in a "complex situation"), and tries to search for rows where `1=0` is true. – jpaugh Oct 24 '16 at 16:46
  • 1
    Also does not copy column's `DATA_DEFAULT` definitions. – user909481 Nov 22 '17 at 08:50
  • @DylanCzenski its only need becase you want only the structure without any data, and this where expression give you zero result just the 'header' – SüniÚr Jul 17 '18 at 12:17
  • @JeffreyKemp... If I need to include index and partitions while creating new table, what should I do? – Vaibhav Gupta Apr 06 '20 at 10:29
  • @VaibhavGupta you're better off just getting the definition of the table (e.g. using dbms_metadata or a tool like SQL Developer) and using that to create your new table. The trick documented here is for quick-and-nasty copies with no bells and whistles. – Jeffrey Kemp Apr 06 '20 at 14:55
91

I used the method that you accepted a lot, but as someone pointed out it doesn't duplicate constraints (except for NOT NULL, I think).

A more advanced method if you want to duplicate the full structure is:

SET LONG 5000
SELECT dbms_metadata.get_ddl( 'TABLE', 'MY_TABLE_NAME' ) FROM DUAL;

This will give you the full create statement text which you can modify as you wish for creating the new table. You would have to change the names of the table and all constraints of course.

(You could also do this in older versions using EXP/IMP, but it's much easier now.)

Edited to add If the table you are after is in a different schema:

SELECT dbms_metadata.get_ddl( 'TABLE', 'MY_TABLE_NAME', 'OTHER_SCHEMA_NAME' ) FROM DUAL;
Dave Costa
  • 47,262
  • 8
  • 56
  • 72
  • How is this command going to be modified if i want to copy from another schema . – HalfWebDev Jul 15 '13 at 09:53
  • `My_table_name` is the existing table . But how do i get the name of my new table created ? – HalfWebDev Jul 18 '13 at 11:44
  • The command in my answer doesn't create the new table; it returns the SQL you would use to recreate the original table. You modify it as desired then run it. So the name of the new table is whatever you choose to specify. – Dave Costa Jul 18 '13 at 15:50
  • 5
    SO it must be like assigning the above sql command to a variable . ryt ? eg . `new_table = dbms_metadata.get_ddl( 'TABLE', 'MY_TABLE_NAME', 'OTHER_SCHEMA_NAME' ). ` Meanwhile please let me know what LONG does here. – HalfWebDev Jul 18 '13 at 16:26
19
create table xyz_new as select * from xyz where rownum = -1;

To avoid iterate again and again and insert nothing based on the condition where 1=2

sunleo
  • 10,589
  • 35
  • 116
  • 196
  • For nowadays, one can also use `FETCH NEXT 0 ROWS ONLY` - some internet sources indicates that might be faster than `rownum`, but for this case, I think rather than performance I prefer the readability of `FETCH` sentence. More up to personal likings probably – Xiang Wei Huang Mar 29 '22 at 07:50
18

Using sql developer select the table and click on the DDL tab

You can use that code to create a new table with no data when you run it in a sql worksheet

sqldeveloper is a free to use app from oracle.

If the table has sequences or triggers the ddl will sometimes generate those for you too. You just have to be careful what order you make them in and know when to turn the triggers on or off.

branchgabriel
  • 4,241
  • 4
  • 34
  • 48
5

You can do this Create table New_table as select * from Old_table where 1=2 ; but be careful The table you create does not have any Index, PK and so on like the old_table.

Vasil Lukach
  • 3,658
  • 3
  • 31
  • 40
Mohsen Molaei
  • 124
  • 1
  • 4
4
    DECLARE
    l_ddl   VARCHAR2 (32767);
BEGIN
    l_ddl      := REPLACE (
                      REPLACE (
                          DBMS_LOB.SUBSTR (DBMS_METADATA.get_ddl ('TABLE', 'ACTIVITY_LOG', 'OLDSCHEMA'))
                        , q'["OLDSCHEMA"]'
                        , q'["NEWSCHEMA"]'
                      )
                    , q'["OLDTABLSPACE"]'
                    , q'["NEWTABLESPACE"]'
                  );

    EXECUTE IMMEDIATE l_ddl;
END; 
Brian Leach
  • 2,025
  • 1
  • 11
  • 14
1

Simply write a query like:

create table new_table as select * from old_table where 1=2;

where new_table is the name of the new table that you want to create and old_table is the name of the existing table whose structure you want to copy, this will copy only structure.

TLama
  • 75,147
  • 17
  • 214
  • 392
1
SELECT * INTO newtable
FROM oldtable
WHERE 1 = 0;

Create a new, empty table using the schema of another. Just add a WHERE clause that causes the query to return no data:

guesswho
  • 462
  • 4
  • 12
1

WHERE 1 = 0 or similar false conditions work, but I dislike how they look. Marginally cleaner code for Oracle 12c+ IMHO is

CREATE TABLE bar AS SELECT * FROM foo FETCH FIRST 0 ROWS ONLY;

Same limitations apply: only column definitions and their nullability are copied into a new table.

Dima Korobskiy
  • 1,479
  • 16
  • 26
1

If one needs to create a table (with an empty structure) just to EXCHANGE PARTITION, it is best to use the "..FOR EXCHANGE.." clause. It's available only from Oracle version 12.2 onwards though.

CREATE TABLE t1_temp FOR EXCHANGE WITH TABLE t1;

This addresses 'ORA-14097' during the 'exchange partition' seamlessly if table structures are not exactly copied by normal CTAS operation. I have seen Oracle missing some of the "DEFAULT" column and "HIDDEN" columns definitions from the original table.

ORA-14097: column type or size mismatch in ALTER TABLE EXCHANGE PARTITION

See this for further read...

pahariayogi
  • 1,073
  • 1
  • 7
  • 18
0

Using pl/sql developer you can right click on the table_name either in the sql workspace or in the object explorer, than click on "view" and than click "view sql" which generates the sql script to create the table along with all the constraints, indexes, partitions etc..

Next you run the script using the new_table_name

Robert
  • 5,278
  • 43
  • 65
  • 115
0

In other way you can get ddl of table creation from command listed below, and execute the creation.

SELECT DBMS_METADATA.GET_DDL('TYPE','OBJECT_NAME','DATA_BASE_USER') TEXT FROM DUAL 
  • TYPE is TABLE,PROCEDURE etc.

With this command you can get majority of ddl from database objects.

Sridhar Sarnobat
  • 25,183
  • 12
  • 93
  • 106
0

copy without table data

create table <target_table> as select * from <source_table> where 1=2;

copy with table data

create table <target_table> as select * from <source_table>;
Alok
  • 61
  • 1
  • 8
0

you can also do a

create table abc_new as select * from abc; 

then truncate the table abc_new. Hope this will suffice your requirement.

Zoltan Toth
  • 46,981
  • 12
  • 120
  • 134
Digo
  • 43
  • 1
  • 11
    Of course, if you have a LOT of data in the original table, this could a really, really bad idea. ;) – Alexios Oct 10 '13 at 15:28
-1
Create table target_table 
As
Select * 
from source_table 
where 1=2;

Source_table is the table u wanna copy the structure of.

Adrian Cid Almaguer
  • 7,815
  • 13
  • 41
  • 63
Prashant Mishra
  • 619
  • 9
  • 25
-1
  1. create table xyz_new as select * from xyz;

-- This will create table and copy all data.

  1. delete from xyz_new;

-- This will have same table structure but all data copied will be deleted.

If you want to overcome the limitations specified by answer: How can I create a copy of an Oracle table without copying the data?

-6

The task above can be completed in two simple steps.

STEP 1:

CREATE table new_table_name AS(Select * from old_table_name);

The query above creates a duplicate of a table (with contents as well).

To get the structure, delete the contents of the table using.

STEP 2:

DELETE * FROM new_table_name.

Hope this solves your problem. And thanks to the earlier posts. Gave me a lot of insight.

Community
  • 1
  • 1
Donkha
  • 7
  • 13
    This even less efficient than the `truncate` version. As well as allocating extents for all the data, you aren't freeing them by deleting, so you're potentially wasting space unless the table grows to the old size. And you're generating undo/redo on both the insert and delete. Jim's answer very simply avoids all of that. – Alex Poole Aug 29 '12 at 07:05