Among other questions, this one asked how to delete from a join.
My question: How much of this is standard SQL? On which databases would this actually work (most not
The Standard SQL-92 syntax required a scalar subquery. This is a relationally solid solution because there is no ambiguity (unlike the proprietary alternatives which can yield unpredictable/unexpected results).
However, one of the drawbacks of the SQL-92 approach is that it can be verbose and involve repetitive constructs e.g.
UPDATE MyTable
SET col1 = (
SELECT T.colA
FROM OtherTable T
WHERE T.ID = MyTable.ID
),
col2 = (
SELECT T.colB
FROM OtherTable T
WHERE T.ID = MyTable.ID
)
WHERE EXISTS (
SELECT *
FROM OtherTable T
WHERE T.ID = MyTable.ID
);
The idea is that the optimizer can recognize the same subquery being reused but in practice vendors have typically not implemented this.
SQL-99 addressed this verbosity and repetition by introducing MERGE
, which was further refined in SQL:2003. It is interesting that nowadays the vendors typically choose to implement new features as per the Standard spec then extend them to provide the features they require, rather than writing wholly proprietary features.
Not standard according to International Standard ISO/IEC 9075:1992 Section 13.6, pages 384-386. Delete with JOIN syntax won't work in Oracle.
The last time I looked at the ANSI standard, the preferred method was subqueries and not JOINs. When dealing with only one implementation, where porting your code is not an issue, then you can use vendor-specific extensions freely, when they are more efficient (though UPDATE FROM, and I imagine DELETE FROM in some scenarios, has proven unpredictable: https://sqlserverfast.com/blog/hugo/2008/03/lets-deprecate-update-from/). Personally, I typically use CTEs for a lot of DELETE operations... but my development is restricted to SQL Server and I don't have to worry much about portability at all. MERGE can also be a good choice when you are performing multiple DML operations, but again this is not implemented the same (or at all) across all vendors.
In your case, I would say stay away from DELETE FROM ... JOIN because the syntax will vary slightly on the three platforms. If you use stored procedures this is less of an issue than if the SQL is embedded in your application(s), but still a hassle nonetheless.
I used to use similar queries when I was on an MS SQL server. Not sure about the others.
this will actually work in Oracle. The FROM keyword is optional: DELETE (query)
is the same as DELETE FROM (query)
.
The rules to DELETE a JOIN are the same as the rules to update a JOIN: Oracle will modify the rows from only one table and only if there is no ambiguity in identifying the rows of the base table. Look in this SO or this SO for example.
Let's build a small example:
CREATE TABLE t_parent (ID NUMBER PRIMARY KEY, NAME VARCHAR2(10));
CREATE TABLE t_child (ID NUMBER PRIMARY KEY,
parent_id NUMBER REFERENCES t_parent);
INSERT INTO t_parent VALUES (1, 'a');
INSERT INTO t_child VALUES (1, 1);
INSERT INTO t_child VALUES (2, 1);
You can delete rows from the CHILD table:
SQL> DELETE FROM (SELECT t_child.*
2 FROM t_child
3 JOIN t_parent ON t_parent.id = t_child.parent_id
4 WHERE t_parent.name = 'a');
2 rows deleted
DELETE ... FROM .. Is not part of the ANSI standards, nor UPDATE ... FROM ... for that matter. This includes any join syntax, since the join can only be specified with a FROM.
All vendors implement this though in one form or another.