> Tom Lane wrote:
> >> What will actually happen (this is a PostgreSQL
> >> extension to the standard) is that an implicit table
> >> reference is added to the FROM clause, so the query is processed
as if
> >> it were written as ...
>
> > I think this extension should be removed.
>
> I don't think it's likely to get removed any time soon.
> Maybe a workable compromise would be to add a GUC parameter
> "allow_implicit_from", with options "ok" (completely permissive),
> "notice" (the current behavior), and "error" (disallow it).
That's a workable compromise indeed.
>
> But we'd have to do something about the DELETE syntax before the
> "error" setting would be real useful.
I agree.
>
> Tom Lane wrote:
> >> AFAIK, statements like
> >> DELETE FROM t1 where t1.id = t2.id ;
> >> are legal. Could the parser still work on this, if the feature
is
> >> removed?
>
> > Only if a new syntax is added.
>
> For UPDATE, we actually do have an extension syntax that allows naming
> secondary tables explicitly:
>
> UPDATE target SET ... FROM other-tables
WHERE ...
>
> The trouble with extending this to DELETE is that DELETE already
uses
> the keyword FROM. Seems like we are stuck with a choice between
>
> DELETE FROM target FROM other-tables
WHERE ...
>
> DELETE FROM target, other-tables
WHERE ...
>
> both of which are bizarre and confusing to my eyes. I think
that MySQL
> uses the second form, which I like even less than the first (it obscures
> the very fundamental semantic difference between the deletion target
and
> the other tables).
>
> Or we could go off with a different keyword, perhaps
>
> DELETE FROM target WITH other-tables
WHERE ...
>
> but that doesn't seem to pass the low-astonishment test either.
USING instead of WITH was suggested last year.
I think this could pass the low-astonishment test.
>
> Comments? It would not be difficult to implement any of these
> alternatives. <hhg>okay, you think it's so easy, *you* decide
> what color it should be</hhg>
>
Jeff Eckermann wrote:
> > What does other Postgres users think about it?
> >
>
> I want to add my vote for keeping the existing
> functionality. I find it _very_ useful, especially
> for interactive work. The spare syntax that can be
> used for update or delete statements greatly enhances
> understandability (and therefore reduces likelihood of
> error) in my experience. Saves typing too :-)
You have my vote.
>
> I would not wish to reduce the functionality of
> PostgreSQL just to save people from themselves.
Me neither.
>
Stephan Szabo wrote:
> > DELETE FROM target WITH other-tables WHERE
...
> >
> > but that doesn't seem to pass the low-astonishment test either.
>
> It'd seem reasonable to use something like SQL99's WITH, although
> that'd put the WITH before the FROM I think. That'd at least
be similar
> to using it in select (admittedly we don't have it yet, but wasn't
someone
> talking about it?)
>
Yes, many were talking about it last year and the year before.
I have saved a pretty subjective selection, which you'll find below.
Thanks for reading.
Regards, Christoph
From: "postgresql" <postgres@lg.ndirect.co.uk>
Subject: [SQL] efficient deletes on subqueries
Date: Tue, 30 Oct 2001 15:33:05 -0000
I have a very large table with > 1 million entries and I wish to delete
rows
which match any entries in a second table.
What is the most efficient way of doing this?
CREATE TABLE AA (keyA integer NOT NULL, info TEXT);
CREATE TABLE obsolete_AA_entries (keyA integer NOT NULL);
I want to remove all entries from AA where keyA matches that from
obsolete_AA_entries,
i.e. SELECT * FROM AA NATURAL JOIN obsolete_AA_entries;
Both of the tables are UNIQUE indiced on keyA.
DELETE FROM AA WHERE EXISTS( SELECT * from obsolete_AA_entries o where AA.keyA = o.keyA);
seems to be faster than
DELETE FROM AA where (keyA) in (SELECT * from obsolete_AA_entries);
However, both are sequentially going through AA which is huge rather
than
looking up values one by one from obsolete_AA_entries which is small.
How do I persuade the database to change its query strategy?
Thanks a lot
Llew
From: Christoph Haller <ch@rodos.fzk.de>
Subject: [SQL] Efficient DELETE Strategies
Date: Mon, 10 Jun 2002 13:42:10 METDST
Hi,
Based on an entry in the mailing list from 30 Oct 2001
about efficient deletes on subqueries,
I've found two ways to do so (PostgreSQL 7.2.1):
1.
BEGIN ;
EXPLAIN ANALYZE
DELETE FROM onfvalue WHERE EXISTS(
SELECT * FROM onfvalue j WHERE
j.sid= 5 AND
onfvalue.lid = j.lid AND
onfvalue.mid = j.mid AND
onfvalue.timepoint = j.timepoint AND
onfvalue.entrancetime < j.entrancetime
) ;
ROLLBACK ;
QUERY PLAN:
Seq Scan on onfvalue
(cost=0.00..805528.05 rows=66669 width=6)
(actual time=61.84..25361.82 rows=24 loops=1) SubPlan -> Index Scan using advncd_onfvalue_idx_stlme on onfvalue j
(cost=0.00..6.02rows=1 width=36) (actual time=0.14..0.14 rows=0 loops=133338)
Total runtime: 25364.76 msec
2.
BEGIN ;
EXPLAIN ANALYZE
INSERT INTO temprefentrancetime(timepoint,lid,mid,sid,entrancetime)
SELECT o.timepoint,o.lid,o.mid,o.sid,o.entrancetime
FROM onfvalue o join onfvalue j ON (
o.lid = j.lid AND
o.mid = j.mid AND
o.timepoint = j.timepoint AND
o.entrancetime < j.entrancetime
) WHERE o.sid= 5 ;
EXPLAIN ANALYZE
DELETE FROM onfvalue WHERE
onfvalue.timepoint = temprefentrancetime.timepoint AND
onfvalue.mid = temprefentrancetime.mid AND
onfvalue.lid = temprefentrancetime.lid AND
onfvalue.sid = temprefentrancetime.sid AND
onfvalue.entrancetime = temprefentrancetime.entrancetime ;
DELETE FROM temprefentrancetime;
ROLLBACK ;
QUERY PLAN:
Merge Join
(cost=16083.12..16418.36 rows=4 width=52)
(actual time=17728.06..19325.02 rows=24 loops=1) -> Sort (cost=2152.53..2152.53 rows=667 width=28) (actual
time=1937.70..2066.46rows=16850 loops=1) -> Index Scan using advncd_onfvalue_idx_stlme on onfvalue
o(cost=0.00..2121.26rows=667 width=28)(actual time=0.57..709.89 rows=16850 loops=1) -> Sort (cost=13930.60..13930.60
rows=133338width=24) (actual time=13986.07..14997.43 rows=133110 loops=1) -> Seq Scan on onfvalue
j(cost=0.00..2580.38rows=133338 width=24)(actual time=0.15..3301.06 rows=133338 loops=1)
Total runtime: 19487.49 msec
QUERY PLAN:
Nested Loop
(cost=0.00..6064.40 rows=1 width=62)
(actual time=1.34..8.32 rows=24 loops=1) -> Seq Scan on temprefentrancetime (cost=0.00..20.00 rows=1000 width=28)
(actualtime=0.44..1.07 rows=24 loops=1) -> Index Scan using advncd_onfvalue_idx_stlme on onfvalue (cost=0.00..6.02
rows=1width=34) (actual time=0.22..0.25 rows=1 loops=24)
Total runtime: 10.15 msec
The questions are:
Is there a way to put the second form (more complicated, but faster)
in one statement?
Or is there even a third way to delete, which I cannot see?
Regards, Christoph
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Mon, 10 Jun 2002 09:56:27 -0400
Christoph Haller <ch@rodos.fzk.de> writes:
> Based on an entry in the mailing list from 30 Oct 2001
> about efficient deletes on subqueries,
> I've found two ways to do so (PostgreSQL 7.2.1):
> ...
> Is there a way to put the second form (more complicated, but faster)
> in one statement?
> Or is there even a third way to delete, which I cannot see?
The clean way to do this would be to allow extra FROM-list relations
in DELETE. We already have a similar facility for UPDATE, so it's not
clear to me why there's not one for DELETE. Then you could do, say,
DELETE FROM onfvalue , onfvalue j WHERE
j.sid= 5 AND
onfvalue.lid = j.lid AND
onfvalue.mid = j.mid AND
onfvalue.timepoint = j.timepoint AND
onfvalue.entrancetime < j.entrancetime ;
If you were using two separate tables you could force this to happen
via an implicit FROM-clause entry, much as you've done in your second
alternative --- but there's no way to set up a self-join in a DELETE
because of the lack of any place to put an alias declaration.
AFAIK this extension would be utterly trivial to implement, since all
the machinery is there already --- for 99% of the backend, it doesn't
matter whether a FROM-item is implicit or explicit. We'd only need to
argue out what the syntax should be. I could imagine
DELETE FROM relation_expr [ , table_ref [ , ... ] ][ WHERE bool_expr ]
or
DELETE FROM relation_expr [ FROM table_ref [ , ... ] ][ WHERE bool_expr ]
The two FROMs in the second form look a little weird, but they help to
make a clear separation between the deletion target table and the
merely-referenced tables. Also, the first one might look to people
like they'd be allowed to write
DELETE FROM foo FULL JOIN bar ...
which is not any part of my intention (it's very unclear what it'd
mean for the target table to be on the nullable side of an outer join).
OTOH there'd be no harm in outer joins in a separate from-clause, eg
DELETE FROM foo FROM (bar FULL JOIN baz ON ...) WHERE ...
Actually, either syntax above would support that; I guess what's really
bothering me about the first syntax is that a comma suggests a list of
things that will all be treated similarly, while in reality the first
item will be treated much differently from the rest.
Does anyone know whether other systems that support the UPDATE extension
for multiple tables also support a DELETE extension for multiple tables?
If so, what's their syntax?
A somewhat-related issue is that people keep expecting to be able to
attach an alias to the target table name in UPDATE and DELETE; seems
like we get that question every couple months. While this is clearly
disallowed by the SQL spec, it's apparently supported by some other
implementations (else we'd not get the question so much). Should we
add that extension to our syntax? Or should we continue to resist it?
regards, tom lane
From: Manfred Koizar <mkoi-pg@aon.at>
Subject: Re: [SQL] Efficient DELETE Strategies
Date: Mon, 10 Jun 2002 22:23:38 +0200
On Mon, 10 Jun 2002 09:56:27 -0400, Tom Lane <tgl@sss.pgh.pa.us>
wrote:
>Does anyone know whether other systems that support the UPDATE
extension
>for multiple tables also support a DELETE extension for multiple
tables?
>If so, what's their syntax?
MSSQL seems to guess what the user wants. All the following
statements do the same:
(0) DELETE FROM t1 WHERE EXISTS (SELECT * FROM t2 WHERE t1.i=t2.i)
(1) DELETE t1 FROM t2 WHERE t1.i=t2.i
(2a) DELETE t1 FROM t2, t1 WHERE t1.i=t2.i
(2b) DELETE t1 FROM t2 INNER JOIN t1 ON t1.i=t2.i
(3a) DELETE t1 FROM t2, t1 a WHERE a.i=t2.i
(3b) DELETE t1 FROM t2 INNER JOIN t1 a ON a.i=t2.i
(4a) DELETE a FROM t2, t1 a WHERE a.i=t2.i
(4b) DELETE a FROM t2 INNER JOIN t1 a ON a.i=t2.i
(5) DELETE t1 FROM t1 a WHERE EXISTS (SELECT * FROM t2 WHERE a.i=t2.i)
(6) DELETE a FROM t1 a WHERE EXISTS (SELECT * FROM t2 WHERE a.i=t2.i)
(0) is standard SQL and should always work. As an extension I'd like
(1) or (2), but only one of them and forbid the other one. I'd also
forbid (3), don't know what to think of (4), and don't see a reason
why we would want (5) or (6). I'd rather have (7) or (8).
These don't work:
(7) DELETE t1 a FROM t2 WHERE a.i = t2.i
"Incorrect syntax near 'a'."
(8) DELETE FROM t1 a WHERE EXISTS (SELECT * FROM t2 WHERE a.i = t2.i)
"Incorrect syntax near 'a'."
Self joins:
(2as) DELETE t1 FROM t1, t1 b WHERE 2*b.i=t1.i
(4as) DELETE a FROM t1 a, t1 b WHERE 2*b.i=a.i
(4bs) DELETE a FROM t1 a INNER JOIN t1 b on 2*b.i=a.i
These don't work:
DELETE t1 FROM t1 b WHERE 2 * b.i = t1.i
"The column prefix 't1' does not match with a table name or alias name
used in the query."
DELETE t1 FROM t1 a, t1 b WHERE 2 * b.i = a.i
"The table 't1' is ambiguous."
And as if there aren't enough ways yet, I just discovered that (1) to
(6) just as much work with "DELETE FROM" where I wrote "DELETE" ...
ServusManfred
From: Tom Lane <tgl@sss.pgh.pa.us>
Bruce Momjian <pgman@candle.pha.pa.us> writes:
> Hannu Krosing wrote:
>> What about
>>
>> DELETE relation_expr FROM relation_expr [ , table_ref [ , ... ] ]
>> [ WHERE bool_expr ]
>>
>> or
>>
>> DELETE relation_expr.* FROM relation_expr [ , table_ref [ , ... ] ]
>> [ WHERE bool_expr ]
> So make the initial FROM optional and allow the later FROM to be a
list
> of relations? Seems kind of strange.
No, I think he's suggesting that one be able to pick out any element of
the FROM-list and say that that is the deletion target. I really don't
want to get into that (unless there is precedent in Oracle or
someplace); it seems way too confusing to me. It would also force us to
do error checking to eliminate cases that ought to just be syntactically
impossible: target table not present, target is a join or subselect
instead of a table, target is on wrong side of an outer join, etc.
[ and in another message ]
> The FROM ... FROM looks weird, and there is clearly confusion over the
> FROM t1, t2. I wish there was another option.
The only other thing that's come to mind is to use a different keyword
(ie, not FROM) for the list of auxiliary relations. WITH might work
from a simple readability point of view:DELETE FROM target WITH other-tables WHERE ...
But we've already got FROM as the equivalent construct in UPDATE, so it
seems weird to use something else in DELETE.
regards, tom lane
From: Tom Lane <tgl@sss.pgh.pa.us>
Manfred Koizar <mkoi-pg@aon.at> writes:
>> If so, what's their syntax?
> MSSQL seems to guess what the user wants.
Gack. Nothing like treating mindless syntax variations as a "feature"
list...
> All the following statements do the same:
> (1) DELETE t1 FROM t2 WHERE t1.i=t2.i
> (2a) DELETE t1 FROM t2, t1 WHERE t1.i=t2.i
> (5) DELETE t1 FROM t1 a
> WHERE EXISTS (SELECT * FROM t2 WHERE a.i=t2.i)
> (6) DELETE a FROM t1 a WHERE EXISTS (SELECT * FROM t2 WHERE a.i=t2.i)
So in other words, MSSQL has no idea whether the name following DELETE
is a real table name or an alias, and it's also unclear whether the name
appears in the separate FROM clause or generates a FROM-item all by
itself. This is why they have to punt on these cases:
> These don't work:
> DELETE t1 FROM t1 b WHERE 2 * b.i = t1.i
> "The column prefix 't1' does not match with a table name or alias name
> used in the query."
> DELETE t1 FROM t1 a, t1 b WHERE 2 * b.i = a.i
> "The table 't1' is ambiguous."
The ambiguity is entirely self-inflicted...
> And as if there aren't enough ways yet, I just discovered that (1) to
> (6) just as much work with "DELETE FROM" where I wrote "DELETE" ...
Hm. So (1) with the DELETE FROM corresponds exactly to what I was
suggesting:DELETE FROM t1 FROM t2 WHERE t1.i=t2.i
except that I'd also allow an alias in there:DELETE FROM t1 a FROM t2 b WHERE a.i=b.i
Given the plethora of mutually incompatible interpretations that MSSQL
evidently supports, though, I fear we can't use it as precedent for
making any choices :-(.
Can anyone check out other systems?
regards, tom lane
From: "Christopher Kings-Lynne" <chriskl@familyhealth.com.au>
> Given the plethora of mutually incompatible interpretations that MSSQL
> evidently supports, though, I fear we can't use it as precedent for
> making any choices :-(.
>
> Can anyone check out other systems?
MySQL:
6.4.6 DELETE Syntax
DELETE [LOW_PRIORITY | QUICK] FROM table_name [WHERE where_definition] [ORDER BY ...] [LIMIT rows]
or
DELETE [LOW_PRIORITY | QUICK] table_name[.*] [,table_name[.*] ...] FROM table-references [WHERE
where_definition]
or
DELETE [LOW_PRIORITY | QUICK] FROM table_name[.*], [table_name[.*] ...] USING table-references [WHERE
where_definition]
DELETE deletes rows from table_name that satisfy the condition given by
where_definition, and returns the number of records deleted.
If you issue a DELETE with no WHERE clause, all rows are deleted. If you
do
this in AUTOCOMMIT mode, this works as TRUNCATE. See section 6.4.7
TRUNCATE
Syntax. In MySQL 3.23, DELETE without a WHERE clause will return zero as
the
number of affected records.
If you really want to know how many records are deleted when you are
deleting all rows, and are willing to suffer a speed penalty, you can
use a
DELETE statement of this form:
mysql> DELETE FROM table_name WHERE 1>0;
Note that this is much slower than DELETE FROM table_name with no WHERE
clause, because it deletes rows one at a time.
If you specify the keyword LOW_PRIORITY, execution of the DELETE is
delayed
until no other clients are reading from the table.
If you specify the word QUICK then the table handler will not merge
index
leaves during delete, which may speed up certain kind of deletes.
In MyISAM tables, deleted records are maintained in a linked list and
subsequent INSERT operations reuse old record positions. To reclaim
unused
space and reduce file-sizes, use the OPTIMIZE TABLE statement or the
myisamchk utility to reorganise tables. OPTIMIZE TABLE is easier, but
myisamchk is faster. See section 4.5.1 OPTIMIZE TABLE Syntax and section
4.4.6.10 Table Optimisation.
The first multi-table delete format is supported starting from MySQL
4.0.0.
The second multi-table delete format is supported starting from MySQL
4.0.2.
The idea is that only matching rows from the tables listed before the
FROM
or before the USING clause are deleted. The effect is that you can
delete
rows from many tables at the same time and also have additional tables
that
are used for searching.
The .* after the table names is there just to be compatible with Access:
DELETE t1,t2 FROM t1,t2,t3 WHERE t1.id=t2.id AND t2.id=t3.id
or
DELETE FROM t1,t2 USING t1,t2,t3 WHERE t1.id=t2.id AND t2.id=t3.id
In the above case we delete matching rows just from tables t1 and t2.
ORDER BY and using multiple tables in the DELETE statement is supported
in
MySQL 4.0.
If an ORDER BY clause is used, the rows will be deleted in that order.
This
is really only useful in conjunction with LIMIT. For example:
DELETE FROM somelog
WHERE user = 'jcole'
ORDER BY timestamp
LIMIT 1
This will delete the oldest entry (by timestamp) where the row matches
the
WHERE clause.
The MySQL-specific LIMIT rows option to DELETE tells the server the
maximum
number of rows to be deleted before control is returned to the client.
This
can be used to ensure that a specific DELETE command doesn't take too
much
time. You can simply repeat the DELETE command until the number of
affected
rows is less than the LIMIT value.
Chris
From: Christoph Haller <ch@rodos.fzk.de>
Bruce Momjian wrote:
> ...
> Yes, another keyword is the only solution. Having FROM after DELETE
> mean something different from FROM after a tablename is just too
weird.
> I know UPDATE uses FROM, and it is logical to use it here, but it is
> just too wierd when DELETE already has a FROM. Should we allow FROM
and
> add WITH to UPDATE as well, and document WITH but support FROM too?
No
> idea. What if we support ADD FROM as the keywords for the new clause?
Sounds like the best solution so far.
Christopher Kings-Lynne wrote:
> DELETE [LOW_PRIORITY | QUICK] table_name[.*] [,table_name[.*] ...]
> FROM table-references
> [WHERE where_definition]
>
> or
>
> DELETE [LOW_PRIORITY | QUICK]
> FROM table_name[.*], [table_name[.*] ...]
> USING table-references
> [WHERE where_definition]
>
> ...
> The idea is that only matching rows from the tables listed before the
FROM
> or before the USING clause are deleted. The effect is that you can
delete
> rows from many tables at the same time and also have additional tables
that
> are used for searching.
Sounds tempting. It is much more what I was asking for.
Is there a collision with USING ( join_column_list ) ?
And it looks like very much work for the HACKERS.
Hannu Krosing wrote:
> ...
> Or then we can just stick with standard syntax and teach people to do
>
> DELETE FROM t1 where t1.id1 in
> (select id2 from t2 where t2.id2 = t1.id1)
>
> and perhaps even teach our optimizer to add the t2.id2 = t1.id1 part
> itself to make it fast
>
> AFAIK this should be exactly the same as the proposed
>
> DELETE FROM t1 FROM t2
> WHERE t2.id2 = t1.id1
This is a fine idea. But it looks like very much work for the HACKERS,
too.
Regards, Christoph
From: Tom Lane <tgl@sss.pgh.pa.us>
Christoph Haller <ch@rodos.fzk.de> writes:
> Christopher Kings-Lynne wrote:
>> DELETE [LOW_PRIORITY | QUICK] table_name[.*] [,table_name[.*] ...]
>> FROM table-references
>> [WHERE where_definition]
>>
>> or
>>
>> DELETE [LOW_PRIORITY | QUICK]
>> FROM table_name[.*], [table_name[.*] ...]
>> USING table-references
>> [WHERE where_definition]
>>
>> The idea is that only matching rows from the tables listed before the
FROM
>> or before the USING clause are deleted. The effect is that you can
delete
>> rows from many tables at the same time and also have additional
tables that
>> are used for searching.
> Sounds tempting. It is much more what I was asking for.
> Is there a collision with USING ( join_column_list ) ?
Good point --- that was a very poor choice of keyword by the MySQL guys.
I have absolutely no intention of getting into this "delete from
multiple tables" business --- I don't understand the semantics it should
have, and it would probably not be easy to do inside Postgres anyway.
It would seem that
DELETE [ FROM ] relation_expr [ alias_clause ][ FROM from_list ] where_clause
is the syntax that would be most nearly compatible with MSSQL and MySQL.
Does Oracle have anything comparable?
regards, tom lane
From: Tom Lane <tgl@sss.pgh.pa.us>
Manfred Koizar <mkoi-pg@aon.at> writes:
> Oracle basically supports (with slight variations between releases
> 7/8/9):
> DELETE [FROM] { table
> | view
> | ( subquery )
> }
> [alias] [WHERE ...] [returning_clause]
Bizarre. How are you supposed to delete from a subquery?
> According to the "SQL Quick Syntax Guide" the WHERE clause is not
> optional. Does anybody know, if this is a documentation bug?
Probably. SQL92 saith:
<delete statement: searched> ::= DELETE FROM <table name> [ WHERE <search condition>
]
<delete statement: positioned> ::= DELETE FROM <table name> WHERE CURRENT OF <cursor
name>
so I could see where a sloppy reader might get confused...
regards, tom lane
From: Manfred Koizar <mkoi-pg@aon.at>
On Wed, 12 Jun 2002 10:49:26 -0400, Tom Lane <tgl@sss.pgh.pa.us>
wrote:
>Manfred Koizar <mkoi-pg@aon.at> writes:
>> Oracle basically supports (with slight variations between releases
>> 7/8/9):
>> DELETE [FROM] { table
>> | view
>> | ( subquery )
>> }
>> [alias] [WHERE ...] [returning_clause]
>
>Bizarre. How are you supposed to delete from a subquery?
Hey, don't blame *me* :-) The thought seems to be, if it is ok to
delete from a view, and a view is just a name for a query, why not
allow to delete from a query. Here is an example out of the reference
manual:DELETE FROM (select * from emp)WHERE JOB = 'SALESMAN'AND COMM < 100;
To be clear: I do *not* think, we need this in PostgreSQL. Otherwise
we'd also have to support delete from the result set of a function ;-)
BTW, I did some more digging. The results are somewhat confusing.
O7: no subquery
O8 v8.0: subquery allowed
O8i v8.1.5: DELETE [ FROM ] table_expression_clause [ where_clause ]
table_expression_clause ::= { schema . { table | view | snapshot } | (
subquery) | table_collection_expression } [ , ... ]
Note, the syntax diagram in the "Oracle8i SQL Reference" claims, that
table_expression_clause can contain more than one table, view, etc.
but this feature(?) is not mentioned in the text. Please, could
someone try this?
O9i: only one table, view, ...DELETE [hint] [FROM]{ dml_table_expression_clause| ONLY ( dml_table_expression_clause )
}[t_alias][where_clause] [returning_clause];
dml_table_expression_clause ::={ [schema .] { table [ { PARTITION ( partition ) | SUBPARTITION ( subpartition
)} | @ dblink ] | { view | materialized view } [@ dblink] }| ( subquery [subquery_restriction_clause] )|
table_collection_expression}
One more thing I found:
Informix XPS (Extended Parallel Server) v8.3 and later allows
DELETE FROM { table | view | synonym } [ { USING | FROM } { table | view | synonym | alias } [ ,
...] ] [ WHERE condition ]
which looks pretty much like your suggestion. Though the semantics
are a bit fuzzy. They require the target table to be listed after the
USING (or second FROM) keyword and give this example:
DELETE FROM lineitemUSING order o, lineitem lWHERE o.qty < 1 AND o.order_num = l.order_num
But what would they do on
DELETE FROM lineitemUSING lineitem l1, lineitem l2WHERE l1.item_num < l2.item_num AND l1.order_num =
l2.order_num
ServusManfred