I need to create table again, so I did the following:
RENAME DOCUMENT TO DOCUMENT_TO_DROP;
ALTER INDEX DOCUMENT_I RENAME TO DOCUMENT_I_XXX;
ALTER INDEX DOCUMENT_II RENAME TO DOCUMENT_II_XXX;
ALTER INDEX DOCUMENT_PK RENAME TO DOCUMENT_PK_XXX ;
Then:
CREATE TABLE "A"."DOCUMENT"
( "SID" NUMBER(15,0), .....
However this end with error:
ORA-00955: name is already used by an existing object.
but
SELECT *
FROM dba_objects
WHERE object_name = upper('DOCUMENT');
-> no rows!
after this i go back to original state
RENAME DOCUMENT_TO_DROP TO DOCUMENT;
-> no error all good.
How is this possible ?
You will see this if your table definition includes a nested table. From comments it seems that it does (but showing the full create statement would still be helpful).
As a simple extension of what you have shown, if I define a table type and include that in the table definition:
create table document (
sid number(15,0),
nt_col nt_type
)
nested table nt_col store as nt_col_nested_tab;
then I get the same error you do:
rename document to document_to_drop;
create table document (
sid number(15,0),
nt_col nt_type
)
nested table nt_col store as nt_col_nested_tab;
ORA-00955: name is already used by an existing object
Depending on how it was defined (when it's a table of objects or of a scalar data type), you might see the nested table name in dba_tables, but it might only appear in dba_nested_tables:
select table_name from user_tables
TABLE_NAME
DOCUMENT_TO_DROP
select table_name from user_nested_tables
TABLE_NAME
NT_COL_NESTED_TAB
So the problem is that you are trying to create a second nested table with the same name. You can rename that as well:
rename nt_col_nested_tab to nt_col_nested_tab_to_drop;
and then the recreation will work:
create table document (
sid number(15,0),
nt_col nt_type
)
nested table nt_col store as nt_col_nested_tab;
and you will see the old and new parent and nested tables in the data dictionary:
select table_name from user_tables
TABLE_NAME
DOCUMENT_TO_DROP
DOCUMENT
select table_name from user_nested_tables
TABLE_NAME
NT_COL_NESTED_TAB_TO_DROP
NT_COL_NESTED_TAB
fiddle
If you change your mind and want to revert the name of the original table you will also probably want to revert the name of the nested table as well.
You might also want to drop the table and use flashback table ... to before drop (docs) to recover it; but test that and make sure flashback is enabled and suitably configured before you do anything drastic...
Can't tell, it isn't obvious at first sight.
Though, I noticed that you're enclosing names into double quotes. My suggestion is NOT to do that.
This is pretty much useless:
SELECT *
FROM dba_objects
WHERE object_name = upper('DOCUMENT'); --> DOCUMENT already is in upper case
Should've been
where upper(object_name) = 'DOCUMENT'
What happens if you run such a query?
I tried to do the same, to see what causes the error:
SQL> create table document
2 (id number constraint pk_doc primary key,
3 id_2 number
4 );
Table created.
SQL> create index document_i on document(id_2);
Index created.
SQL> rename document to document_to_drop;
Table renamed.
SQL> alter index document_i rename to document_i_xxx;
Index altered.
At first I though it might be because of a constraint, but - nope, error code is different:
SQL> create table document
2 (id number constraint pk_doc primary key,
3 id_2 number
4 );
(id number constraint pk_doc primary key,
*
ERROR at line 2:
ORA-02264: name already used by an existing constraint
Is it a table? Seems so, it raises ORA-00955:
SQL> create table document_to_drop
2 (id number constraint pk_do2c primary key,
3 id_2 number
4 );
create table document_to_drop
*
ERROR at line 1:
ORA-00955: name is already used by an existing object
SQL>
Perhaps it is some kind of a bug in Oracle. Which version do you use?
Recently, I had 2 database links with exactly the same name; when I tried to drop any of them, I got "ORA-03113: end-of-file on communication channel" error. DBA bounced the database and it "solved" the problem. Can you do that? I'm not saying that it'll actually help (besides, your problem is different than mine) but - if nothing else helps, try it.
I've created an VOLATILE MUTISET TABLE with name tmp, and then trying to create another table as merging tmp and permanent table.
It results in Error 3806: Table/view/trigger name 'tmp' is ambiguous
What am I doing wrong?
CREATE MULTISET VOLATILE TABLE tmp2 AS
(
SEL
a.*,
tmp.id
from library.table a
inner join tmp
on a.sk = tmp.sk
)
WITH DATA
PRIMARY INDEX (id)
ON COMMIT PRESERVE ROWS
The following entry in Teradata manual says the following:
Resolving Table References
When encountering an unqualified table name, the system looks for a table by that name in all of the following databases.
The default database
Any databases referenced by the SQL request
The logon user database for a volatile table by that name
The search must find the table name in only 1 of those databases. Teradata Database returns the “ambiguous table name” error message if the table name exists in more than 1 of those databases.
I have a table old_table (In oracle 10g)
I have to copy entire data of old_table into new_table.
At that moment, I will use
create table new_table
as
select * from old_table
Will this command create a table exactly like old_table?
For example, if old_table have some indexes on some columns.
If I use the above command, then, the new_table also have same indexes?
It will only create table with default settings and same structure (same columns and column types) as original table. It will not create any indexes, constraints, grants, triggers and any other objects dependent on the original table.
You can try this
create table new_table as select * from old_table
where 1=2;
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.)
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;
I want to duplicate a table schema, but only if the target table does not yet exist:
CREATE TABLE IF NOT EXISTS my_table_secondary as select * from my_table_primary
Problem: running this if the my_secondary_table exists results in:
ERROR: Syntaxerror at "as".
What could I do to make this sql statement work?
(postgres 9.4)
To duplicate the schema of a table, you need a completely different syntax.
create table if not exists my_table_secondary (
like my_table_primary including all
);
INCLUDING ALL is an abbreviated form of INCLUDING DEFAULTS INCLUDING
CONSTRAINTS INCLUDING INDEXES INCLUDING STORAGE INCLUDING COMMENTS.
It doesn't duplicate foreign key constraints. See CREATE TABLE. Search for "The LIKE clause".
Try this approach:
CREATE OR REPLACE VIEW my_view AS SELECT * FROM my_table_primary;
CREATE TABLE IF NOT EXISTS my_table_secondary LIKE my_view;
INSERT INTO my_table_secondary
SELECT * FROM my_view
WHERE NOT EXISTS ( SELECT * FROM my_table_secondary );
More on CREATE TABLE ... LIKE: http://www.postgresql.org/docs/9.1/static/sql-createtable.html
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?
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
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;
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
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.
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.
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;
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.
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:
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.
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...
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.
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
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>;
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.
Create table target_table
As
Select *
from source_table
where 1=2;
Source_table is the table u wanna copy the structure of.
create table xyz_new as select * from xyz;
-- This will create table and copy all data.
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?
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.