0

TableA と TableB という 2 つのテーブルがあります。

TableA には次のフィールドがあります。

TableA_ID
FileName

TableB には次のフィールドがあります。

TableB_ID
TableA_ID
CreationDate

TableA_ID フィールドの 2 つのテーブル間に外部キー リンクがあります。

両方のテーブルからレコードを削除する必要があります。TableB の「CreationDate」を調べて、特定の日付より後であれば、そのレコードを削除する必要があります。また、TableB のレコードと同じ TableA_ID を持つ TableA のレコードを削除する必要があります。

TableA_ID (1 対多の関係) を使用する複数のレコードが TableB に存在する場合があります。そのため、TableB のエントリがまだ使用している場合、TableA のレコードを削除できません。

これは単一のステートメントで実行できないことはわかっていますが、トランザクションで実行できることを嬉しく思います。私が抱えている問題は、これを行う方法がわからないことです。MS SQL Server 2008 を使用しています。可能であればトリガーを使用したくありません。

4

3 に答える 3

5

TableBに一致するレコードがないTableAにレコードが存在する可能性はありますか?そうでない場合は、TableBから削除した後、TableA内の一致しないレコードを削除できることがわかります。

begin transaction
delete from TableB
where CreationDate > @SomeDate

delete from TableA
where TableA_ID not in (select TableA_ID from TableB)
end transaction

さもないと:

begin transaction
-- Save the TableA_IDs being deleted:
select distinct TableA_ID
into #TableA_Delete
from Table_B
where CreationDate > @Somedate

-- Depending on the expected size of #TableA_Delete, you may want 
-- to create an index here, to speed up the delete from TableA.

delete from TableB
where CreationDate > @SomeDate

delete from TableA
where TableA_id in (select TableA_Id from #TableA_Delete)
and TableA_id not in (select TableA_id from TableB)
commit transaction

上記の両方のソリューションでは、エラー処理を追加する必要があります。

また、IDを一時的に保存する別の方法については、NYSystemsAnalystを参照してください。

于 2009-12-17T17:07:07.313 に答える
0

編集: 申し訳ありませんが、TableB に複数のレコードがある場合、TableA エントリを保持する必要があるという質問の部分は見当たりませんでした。代わりにこれを使用してください:

/* Table valued variable to hold Table A IDs to be deleted. */
DELCARE @IDs AS table
(
    ID int
);

/* Get the TableA IDs that are subject to deletion. */
INSERT INTO @IDs (
    ID
)SELECT TableA_ID
FROM TableB
WHERE CreationDate >= @MyCreationDate)
GROUP BY TableA_ID
HAVING (COUNT(TableA_ID) = 1); /* Only get IDs that appear once in TableB */

/* Delete the TableB records. */
DELETE b
FROM TableB AS b
WHERE CreationDate >= @MyCreationDate);

/* Delete the TableA records. */
DELETE a
FROM TableA AS a
    INNER JOIN @IDs AS c ON (a.TableA_ID = c.ID);

データの整合性を確保するために、これらすべてをトランザクションでラップする必要があります。

于 2009-12-17T16:48:19.333 に答える
0

親が削除されると、参照整合性は子行を削除する必要があります。カスケード削除が有効になっていることを確認してください。

そうしないと、子レコード用と親レコード用の 2 つの削除ステートメントを挿入する必要があります。

DELETE FROM TableB INNER JOIN TableA ON TableA.TableAID = TableB.TableAID WHERE CreationDate >= SomeDate

DELETE FROM TableA WHERE TableAID=SomeID
于 2009-12-17T16:45:02.757 に答える