サブクエリを使用してSQLを削除する方法


15

次のコードは、テーブルから重複するレコードを削除するために開発者の1人によって追加されました。

DELETE  SubQuery

FROM
(
    SELECT  ID
            ,FK1
            ,FK2
            ,CreatedDateTime
            ,ROW_NUMBER() OVER(PARTITION BY FK1, FK2 ORDER BY CreatedDateTime) AS RowNumber

    FROM    Table
)
AS SubQuery

WHERE   RowNumber > 1

コードをレビューするとき、私はそれが機能しないと仮定しましたが、テスト環境(SQL 2014)でテストするとそれが機能することがわかります!

SQLはサブクエリを解決し、レコードを削除する方法をどのように知っていますかtable

回答:


14

subqueryあなたのコードを持っているが呼び出され、派生テーブル。これはベーステーブルではなく、クエリの実行中に「存続する」テーブルです。ビュービューテーブルとも呼ばれます)と同様に、最近のバージョンでは、クエリ内のテーブルを「定義」する別の4番目の方法であるCTEは、多くの点でテーブルに似ています。あなたはすることができselect、そこから、あなたはそれらを使用することができますfromかにjoin他のテーブルにそれら(ベース又はません!)。

一部のDBMSでは(すべてのDBMSがこれを同じ方法で実装しているわけではありません)、これらのテーブル/ビューは更新可能です。また、我々はできることと、「更新可能」とはupdateinsert中またはdeleteそれらから。

ただし、制限があり、これは予想されています。subqueryが2(または17個のテーブル)の結合であったと想像してください。どういうdelete意味でしょうか?(どのテーブルから行を削除する必要がありますか?)更新可能なビューは非常に複雑な問題です。関係理論の有名な専門家であるクリス・デイトによって書かれた最近の(2012年の)本(完全にこの主題に関する):ビューの更新と関係理論があります。

派生テーブル(またはビュー)が非常に単純なクエリである場合、ベーステーブルが1つだけで(aによって制限される場合がありますWHERE)、noのGROUP BY場合、派生テーブルのすべての行は基礎となるベーステーブルの1行に対応するため、簡単*このからの更新、挿入または削除します。

サブクエリ内のコードがより複雑な場合、派生テーブル/ビューの行を、基礎となるベーステーブルのいずれかの行にトレース/解決できるかどうかに依存します。

SQL Serverについては、MSDNの更新可能なビューの段落で詳細を参照できますCREATE VIEW

更新可能なビュー

次の条件が満たされる限り、ビューを介して基になるベーステーブルのデータを変更できます。

  • いずれかを含む修飾、UPDATEINSERT、およびDELETEステートメントは、唯一のベーステーブルの列を参照する必要があります。

  • ビューで変更される列は、テーブル列の基になるデータを直接参照する必要があります。列は、次のような他の方法で導出することはできません。

  • 集約関数:AVGCOUNTSUMMINMAXGROUPINGSTDEVSTDEVPVAR、とVARP

  • 計算。他の列を使用する式から列を計算することはできません。集合演算子を用いて形成されている列UNIONUNION ALLCROSSJOINEXCEPT、及びINTERSECT 演算に量とも更新できません。

  • 修飾されている列は影響を受けませんGROUP BYHAVINGまたはDISTINCT句。

  • TOPWITH CHECK OPTION句とともにビューのselect_statementのどこにも使用されません。

前述の制限FROMは、ビュー自体に適用されるのと同様に、ビューの句内のすべてのサブクエリに適用されます。一般に、データベースエンジンは、ビュー定義から1つのベーステーブルへの変更を明確にトレースできる必要があります。


実際にdeleteはの方が簡単で、より複雑ではありませんupdate。SQL Serverに必要なのは、削除するベーステーブルの行を識別するための主キーまたはその他の方法のみです。ためにupdate、我々は計算列を更新できないことを(むしろ明白な)追加の制限があります。クエリを変更して更新を試みることができます。更新CreatedDateTimeはおそらく問題なく動作しますが、計算RowNumber列を更新しようとするとエラーが発生します。そしてinsert、私たちが持っていないベーステーブルのすべての列に値を指定する必要があるだろうとして、さらに複雑であるDEFAULT制約を。


4

クエリプランを見ると簡単にわかります。あなたの場合、計画には、行番号を処理するための追加のセグメントおよびシーケンスプロジェクト演算子が含まれています。このタイプの操作は、SQL Serverが基になるテーブルを実際に解決できる場合にのみ機能します。

サブクエリとCTEからの削除は完全にサポートされており、特に重複を削除する場合に非常に効率的です。また、古いバージョンのSQL Serverで使用したことを思い出すようです。

私の古いブログ投稿でもっと。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.