公開日の学びではないのですが、Today I Learnedです。
目次
出発点:EXISTSと挫折結合を知った記事
2つのテーブルを扱いました。
- Products
- Order_Details
Order_Detailsにない(=注文されていない)Products(=製品)を一覧。
このクエリの書き方が挫折結合です。
SELECT p.ProductNumber, p.ProductName FROM Products AS p LEFT JOIN Order_Details od on p.ProductNumber = od.ProductNumber WHERE od.ProductNumber IS NULL;
+---------------+--------------------------------+ | ProductNumber | ProductName | +---------------+--------------------------------+ | 4 | Victoria Pro All Weather Tires | | 23 | Ultra-Pro Skateboard | +---------------+--------------------------------+ 2 rows in set (0.01 sec)
こちらの挫折結合のクエリをベースに、条件に該当するレコードを片方のテーブルから削除していきます。
JOINした条件でDELETEする
(現実にはやらないと思いますが練習のための例として)Order_Detailsにない(=注文されていない)製品をProductsから消します。
挫折結合のクエリを以下のように書き換えます。
DELETE p FROM Products AS p LEFT JOIN Order_Details od on p.ProductNumber = od.ProductNumber WHERE od.ProductNumber IS NULL;
私にとっての学びは「DELETE p FROM
」と、DELETEの直後にテーブル名のエイリアスが登場する点。
JOINを使わずに単一のテーブルから削除するとき、「DELETE FROM Products
」じゃないですか
ドキュメントの「複数テーブル構文」より抜粋
DELETE tbl_name[.*] [, tbl_name[.*]] ... FROM table_references [WHERE where_condition]
同じドキュメントの「複数テーブルの削除」より
table_references 句は、結合に含まれるテーブルをリストします。
JOINを書くと、SQLの構文的にはtable_referencesに該当するわけですね
FROM 句の前にリストされているテーブルの一致する行のみが削除されます。
JOIN(table_reference)のうちのどのテーブルの行を削除するかを示すために、「DELETE p FROM
」となると理解しました。
ProductsとOrder_Detailsに向けて流してみます。
-- 40 SELECT COUNT(1) FROM Products; -- Productsのレコードを消せるように、外部キー制約を外す(今回は練習目的なので) ALTER TABLE Product_Vendors DROP CONSTRAINT Product_Vendors_FK00; -- 2件ともある SELECT * FROM Products WHERE ProductNumber IN (4, 23); DELETE p FROM Products AS p LEFT JOIN Order_Details od on p.ProductNumber = od.ProductNumber WHERE od.ProductNumber IS NULL; -- Empty set SELECT * FROM Products WHERE ProductNumber IN (4, 23); -- 38 SELECT COUNT(1) FROM Products;
終わりに
MySQLで2つのテーブルをJOINした条件で、片方のテーブルからDELETEするには、「DELETE エイリアス FROM
」のように書くことを知りました
DELETE [消したいテーブルのJOINで使っているエイリアス] FROM [JOINを書く。例に使ったのは挫折結合] WHERE [条件];