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.
Related
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.
So I'm trying to create a copy of one of my tables into an index organized table, However I get an error, here is the code.
create table clients2 as
select *
from clients
organization index;
ORA-00933:"SQL command not properly ended"
Your command is wrong.
SQL> create table testiot ( object_id primary key,object_name )
organization index
as select object_id,object_name from dba_objects
where object_id is not null ;
Table created.
SQL> select count(*) from testiot ;
COUNT(*)
----------
208730
Organization index must be in the definition of the table and before as select. On the other hand, you need to define the columns in the table and which one is the primary key for IOT.
I think I just found an error in DB2 itself. When I run this code I expect it to throw an error when executing the delete statement (the subselect wrongly uses A_NAME instead of NAME). But: it acts as if there was no where clause and deletes all the rows in table NAMES!
CREATE TABLE NAMES (A_NAME VARCHAR(20));
CREATE TABLE OLDNAMES (NAME VARCHAR(20));
INSERT INTO NAMES VALUES ('ANNA'), ('ELLA'), ('JOHN'), ('EARL');
INSERT INTO OLDNAMES VALUES ('ELLA'), ('EARL');
-- this should throw an error message:
DELETE FROM NAMES WHERE A_NAME IN (SELECT A_NAME FROM OLDNAMES);
-- this should show ANNA & JOHN if the subselect
-- was correct, but shows nothing
SELECT * FROM NAMES;
-- cleanup
DROP TABLE NAMES;
DROP TABLE OLDNAMES;
I ran it on a DB2/LINUXX8664 10.5.9
Or is "not a bug, but a feature"?!
You are wrong. SQL has scoping rules for resolving column references in subqueries. If the column reference is not resolved in the inner query, then it looks to the outer query.
These are the rules of SQL, not specific to DB2.
That is SQL interprets your logic as:
DELETE FROM NAMES
WHERE NAMES.A_NAME IN (SELECT NAMES.A_NAME FROM OLDNAMES ON);
And this is valid -- if meaningless -- SQL.
This is why qualifying ALL column references is recommended. The better way to write this query is:
DELETE FROM NAMES
WHERE NAMES.A_NAME IN (SELECT ON.A_NAME FROM OLDNAMES ON);
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
This seems so simple, but I haven't been able to find an answer to this question.
What do I want? A master table with rows that delete themselves whenever they are not referenced (via foreign keys) anymore. The solution may or may not be specific to PostgreSql.
How? One of my approaches to solving this problem (actually, the only approach so far) involves the following: For every table that references this master table, on UPDATE or DELETE of a row, to check for the referenced row in master, how many other other rows still refer to the referenced row. If it drops down to zero, then I delete that row in master as well.
(If you have a better idea, I'd like to know!)
In detail:
I have one master table referenced by many others
CREATE TABLE master (
id serial primary key,
name text unique not null
);
All the other tables have the same format generally:
CREATE TABLE other (
...
master_id integer references master (id)
...
);
If one of these are not NULL, they refer to a row in master. If I go to this and try to delete it, I will get an error message, because it is already referred to:
ERROR: update or delete on table "master" violates foreign key constraint "other_master_id_fkey" on table "other"
DETAIL: Key (id)=(1) is still referenced from table "other".
Time: 42.972 ms
Note that it doesn't take too long to figure this out even if I have many tables referencing master. How do I find this information out without having to raise an error?
You can do one of the following:
1) Add reference_count field to master table. Using triggers on detail tables increase the reference count whenever a row with this master_id is added. Decrease the count, when row gets deleted. When reference_count reaches 0 - delete the record.
2) Use pg_constraint table (details here) to get the list of referencing tables and create a dynamic SQL query.
3) Create triggers on every detail table, that deletes master_id in main table. Silence error messages with BEGIN ... EXCEPTION ... END.
In case someone wants a real count of rows in all other tables that reference a given master row, here is some PL/pgSQL. Note that this works in plain case with single column constraints. It gets more involved for multi-column constraints.
CREATE OR REPLACE FUNCTION count_references(master regclass, pkey_value integer,
OUT "table" regclass, OUT count integer)
RETURNS SETOF record
LANGUAGE 'plpgsql'
VOLATILE
AS $BODY$
declare
x record; -- constraint info for each table in question that references master
sql text; -- temporary buffer
begin
for x in
select conrelid, attname
from pg_constraint
join pg_attribute on conrelid=attrelid and attnum=conkey[1]
where contype='f' and confrelid=master
and confkey=( -- here we assume that FK references master's PK
select conkey
from pg_constraint
where conrelid=master and contype='p'
)
loop
"table" = x.conrelid;
sql = format('select count(*) from only %s where %I=$1', "table", x.attname);
execute sql into "count" using pkey_value;
return next;
end loop;
end
$BODY$;
Then use it like
select * from count_references('master', 1) where count>0
This will return a list of tables that have references to master table with id=1.
SELECT *
FROM master ma
WHERE EXISTS (
SELECT *
FROM other ot
WHERE ot.master_id = ma.id
);
Or, the other way round:
SELECT *
FROM other ot
WHERE EXISTS (
SELECT *
FROM master ma
WHERE ot.master_id = ma.id
);
SO if you want to update (or delete) only the rows in master that are not referenced by other, you could:
UPDATE master ma
SET id = 1000+id
, name = 'blue'
WHERE name = 'green'
AND NOT EXISTS (
SELECT *
FROM other ot
WHERE ot.master_id = ma.id
);