ORA-01752: cannot delete from view without exactly one key-preserved table
Parthiban Nagarajan, January 28, 2010 - 7:09 am UTC
Hi Tom
create table tname_a (x int primary key);
create table tname_b (x int primary key references tname_a);
delete (
select a.x, b.x from tname_a a, tname_b b
);
delete (
*
ERROR at line 1:
ORA-01752: cannot delete from view without exactly one key-preserved table
Why we are not able to delete from two tables at a time (in single SQL) ?
Oracle can decide the relationship with the data dictionary and then can delete TNAME_B first and then delete TNAME_A ... (If we can interpret this from the above script, ORACLE can do a lot regarding this, I hope ...)
If so, why it is raising the error ORA-01752 ?
January 29, 2010 - 3:41 pm UTC
... Why we are not able to delete from two tables at a time (in single SQL) ? ...
because it is against the rules, that is all. If we cannot determine which SINGLE TABLE is the target of the delete - we cannot do it.
If you want to, you could write an instead of delete trigger to delete from both.
Re: ORA-01752
Parthiban Nagarajan, February 01, 2010 - 9:53 pm UTC
Hi Tom
Thanks for your reply. But my doubt seems not cleared yet.
<quote> ... we cannot determine which SINGLE TABLE is the target of the delete ... </quote>
Why you want to target only a SINGLE TABLE ?
If I want it to be a single table, I would have written like ...
delete from tname_a;
But, I need to delete from more than one table in a single SQL. Thats why I have written ...
delete (a_query_with_join);
So, can you please tell me why Oracle wants to delete only from a Single Table ?
February 02, 2010 - 12:15 pm UTC
... Why you want to target only a SINGLE TABLE ? ..
because the rule of DELETE is... you delete from a single table, period, that is it, that is the rule, that is the standard, that is the definition of DELETE.
It is not Oracle, is is SQL.
... But, I need to delete from more than one table in a single SQL....
no, you don't need to delete from more than one table, you can and will use a delete per table.
Re: ORA-01752
Parthiban Nagarajan, February 02, 2010 - 8:37 pm UTC
Hi Tom
Thanks for your explanation.
I am not happy with this rule of SQL. :(
Let it be the rule of SQL but not the rule of Oracle itself. ;)
It would be very useful and interesting if Oracle provides the multi-table delete in single SQL in coming versions.
Once again, Thanks.
February 03, 2010 - 9:55 am UTC
.. It would be very useful and interesting if Oracle provides the multi-table
delete in single SQL in coming versions.
...
I disagree.
It would ONLY make sense in a 1:1 relationship. Never in a one to many.
And if you ask me, a 1:1 relationship is something that is OK in a logical model, but you do not do that in a physical design. There would be one table.
Hence, if you find yourself constantly in need of this, in my opinion, you've done it wrong.
unpredictability of the deleted table in a DELETE JOIN
Vincent Malgrat, February 08, 2010 - 5:03 am UTC
Greetings Tom,
I agree with you that only one table will be deleted in a DELETE JOIN, however I have found that when several tables are key-preserved there is no raised exception (in contradiction with the error message "
exactly one key-preserved table"). In the case when there are two key-preserved tables, IMO Oracle should raise an exception because there is an ambiguity as to which table will be deleted. Instead, Oracle seems to choose the first table in the FROM list (?!):
SQL> select * from v$version;
BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - 64bi
PL/SQL Release 10.2.0.3.0 - Production
CORE 10.2.0.3.0 Production
TNS for IBM/AIX RISC System/6000: Version 10.2.0.3.0 - Productio
NLSRTL Version 10.2.0.3.0 - Production
SQL> CREATE TABLE tname_a (x INT PRIMARY KEY);
Table created
SQL> CREATE TABLE tname_b (x INT PRIMARY KEY);
Table created
SQL> INSERT INTO tname_a VALUES (1);
1 row inserted
SQL> INSERT INTO tname_a VALUES (2);
1 row inserted
SQL> INSERT INTO tname_b VALUES (1);
1 row inserted
SQL> DELETE (SELECT a.x, b.x FROM tname_a a, tname_b b WHERE a.x = b.x);
1 row deleted
SQL> SELECT * FROM tname_a;
X
---------------------------------------
2
SQL> SELECT * FROM tname_b;
X
---------------------------------------
1
SQL> -- ** We see that Oracle deleted one row in tname_a,
SQL> -- let's try to reverse the order of the DELETE **:
SQL> INSERT INTO tname_a VALUES (1);
1 row inserted
SQL> DELETE (SELECT a.x, b.x FROM tname_b b, tname_a a WHERE a.x = b.x);
1 row deleted
SQL>
SQL> SELECT * FROM tname_a;
X
---------------------------------------
1
2
SQL> SELECT * FROM tname_b;
X
---------------------------------------
SQL> -- ** Here Oracle deleted one row in tname_b **