2016-10-10 6 views
2

2つのデータベースからいくつかの行を削除するSQL Serverスクリプトを作成するのが難しいです。このトピックでは他にもいくつか質問がありましたが、このシナリオではうまくいかないようです。私はそのような基本的な質問について事前にお詫びしますが、これは検索に悩まされることがありません。私は多くのデータを照会しますが、テーブルへの書き込みはめったにありません。SQL Server:1つのテーブルの情報を使用して別のテーブルの行を削除する

私は

defects.roll_id = rollinfo.roll_idx 

rollinfo.num_defects呼ばrollinfoテーブルの列がありますによってリンクされている2つのテーブルrollinfodefectsを持っています。

この値が@MAX_DEFECTSより大きい場合は、削除します。さらに、対応する行をdefectsテーブルから削除したいとします。この情報を選択

は簡単です:

SELECT 
    D.ROLL_ID, 
    R.ROLL_IDX 
FROM 
    VISION17SLITTER.DBO.ROLLINFO R 
INNER JOIN 
    VISION17SLITTER.DBO.DEFECTS D ON D.ROLL_ID = R.ROLL_IDX 
WHERE 
    R.NUM_DEFECTS > @MAX_DEFECTS 

私はいくつかの種類を行う必要がある場合、行は削除するだけで、SELECTステートメントを変更することにより、一度に二つのテーブルから削除されたりすることができれば、私は確認されませんでしたが"where exists"ステートメント。

レコードの場合、これは約200k行になるため、これを行う方法が複数ある場合は、どちらが効率的かを知りたいと思います。

おかげで、

ダン

+0

あなたは一度だけの欠陥を削除するために、彼らは、関連テーブルから削除される必要がありますので使用は、 '外部キー制約DELETE'カスケードを使用することができます。 –

+0

[1つのクエリで2つのテーブルから削除]の可能な複製(http://stackoverflow.com/questions/1233451/delete-from-two-tables-in-one-query) – pid

答えて

3

あなたは2つのテーブルから削除する必要があるので、あなたは2つのDELETE文を持っている必要がありますので、私は最善のアプローチは、と思うだろうあなたが一時的なテーブルに削除する必要があるそれらのIDを書くために、 Dその後、あなたの2つのDELETE文を駆動するためにそれを使用:

-- create the temp table - you didn't mention what the datatype for these two columns is - adapt as needed 
CREATE TABLE #IDsToBeDeleted (ID INT NOT NULL) 

-- select those ID's you want to delete into the temp table 
INSERT INTO #IDsToBeDeleted (ID) 
    SELECT 
     D.ROLL_ID 
    FROM 
     VISION17SLITTER.DBO.ROLLINFO R 
    INNER JOIN 
     VISION17SLITTER.DBO.DEFECTS D ON D.ROLL_ID = R.ROLL_IDX 
    WHERE 
     R.NUM_DEFECTS > @MAX_DEFECTS 

-- based on the temp table, now delete from the two tables 
-- again, from your question it isn't entirely clear which 
-- is the "parent" table, and which the "child" table - so you 
-- might need to change the order of deleting those rows to 
-- match your situation 

BEGIN TRANSACTION 
BEGIN TRY  
    DELETE FROM VISION17SLITTER.DBO.DEFECTS 
    WHERE ROLL_ID IN (SELECT ID FROM #IDsToBeDeleted)  

    DELETE FROM VISION17SLITTER.DBO.ROLLINFO 
    WHERE ROLL_IDX IN (SELECT ID FROM #IDsToBeDeleted) 

    COMMIT TRANSACTION 
END TRY 
BEGIN CATCH 
    -- report and log the error 
    ROLLBACK TRANSACTION 
END CATCH 
+0

marc_s、それは私が文を削除する必要があると思った多くの意味があります。私はこれを試してみましょう。 – mreff555

+0

ROLLINFOから削除している間に最初のテーブルが削除された後に問題が発生した場合に備えて、トランザクションでそれをラップすることをお勧めします。そうしないと、IDリストを再作成して削除を再実行できないことがあります。 –

+0

@EdwardComeau:絶対に - その事実を強調するために私の応答を更新しました –

0

は、あなたはこれを試したことがありますか?

これは、DBに応じて動作する場合と動作しない場合があります。

DELETE D, R 
FROM 
    VISION17SLITTER.DBO.ROLLINFO R 
    INNER JOIN 
    VISION17SLITTER.DBO.DEFECTS D 
    ON D.ROLL_ID = R.ROLL_IDX 
WHERE R.NUM_DEFECTS > @MAX_DEFECTS; 

は、そうでない場合は、同じバッチ内の2件の削除を使用します(あなたがスクリプトを書きたいと言うので、バッチが行うには正しいものです)。あなたはすでにあなたがDBとの対話人だけだということを知っているので、この単純なケースでは、トランザクションを必要としません:あなたは本当に手動で起動するためのスクリプトをしたくない場合は

DELETE D 
FROM 
    VISION17SLITTER.DBO.ROLLINFO R 
    INNER JOIN 
    VISION17SLITTER.DBO.DEFECTS D 
    ON D.ROLL_ID = R.ROLL_IDX 
WHERE R.NUM_DEFECTS > @MAX_DEFECTS; 

DELETE R 
FROM 
    VISION17SLITTER.DBO.ROLLINFO R 
WHERE R.NUM_DEFECTS > @MAX_DEFECTS; 

GO 

アプリケーションスタンドながら、それでも、あなたは並行性を考慮しなければなりませんし、実際の取引は、オーダーである:

BEGIN TRANSACTION 

    DELETE D 
    FROM 
    VISION17SLITTER.DBO.ROLLINFO R 
    INNER JOIN 
    VISION17SLITTER.DBO.DEFECTS D 
    ON D.ROLL_ID = R.ROLL_IDX 
    WHERE R.NUM_DEFECTS > @MAX_DEFECTS; 

    DELETE R 
    FROM 
    VISION17SLITTER.DBO.ROLLINFO R 
    WHERE R.NUM_DEFECTS > @MAX_DEFECTS; 

COMMIT; 
+2

2つのテーブルから削除することはできません1つの 'DELETE'ステートメント。 –

+0

は真実ではありませんが、DBの実装に依存しています。オラクルとMySQL(innodb)のバージョンがサポートされているので、両方のソリューションを提示しています(OPがテストしなければならない) in。 – pid

+1

まあ、質問はそのような構文をサポートしていない[sql-server]とタグ付けされています。一方、私は他のDBMSがそれをサポートするかもしれないことを認識しませんでした。私は今日何か新しいことを学んだ。ありがとう。 –

関連する問題