Hibernateで生成されたOracleデータベースを分析したところ、単一のテーブルから行を削除すると、子テーブルの関連する行を削除するために1200以上のトリガーが発生することがわかりました。トリガーはすべて同じように自動生成されます。最初に存在を確認せずに子行を自動的に削除します。どの子テーブルに実際に関連する行があるかを予測することは不可能であるため、深く分岐した完全に空のリムでカスケード削除が実行されないようにするための実行可能な解決策は、関連する行の存在を確認してから実行することだと思います。消去。他のdbmsでは、削除する前に「存在する場合.....」と単純に述べることができます。オラクルでこれを行うための同等の方法はありますか?
4 に答える
「単一のテーブルから行を削除すると、1200以上のトリガーが発生します」これらのステートメントまたは行レベルのトリガーですか?後者の場合、行が削除された場合にのみ起動します。顧客にBEFOREDELETEトリガーを設定して顧客の注文を削除し、注文にBEFOREDELETEトリガーを設定して注文アイテムを削除するとします。顧客に注文がなく、注文テーブルトリガーが行レベルのトリガーである場合、注文アイテムからの削除は実行されません。
「削除を試みる前に、関連する行の存在を確認してください」おそらく利点はありません。実際、SELECTの後にDELETEを指定すると、より多くの作業が実行されます。
もちろん、Hibernateロジックは壊れています。削除セッションでは、コミットされたトランザクションのみが表示されます(削除が試みられます)。FREDが顧客の注文を挿入したが、それがコミットされていない場合、JOHNの削除(トリガーを介して)はそれを認識しないか、削除しようとしません。ただし、それでも「成功」し、親顧客を削除しようとします。データベースで外部キー制約を実際に有効にしている場合、Oracleが起動します。FREDがコミットするまで待機し、子があるため削除を拒否します。外部キー制約が設定されていない場合は、存在しない顧客の注文があります。これが、この種のビジネスロジックをデータベースに適用する必要がある理由です。
可能であれば、DBテーブルを適切に変更および設定してください。-DBAを自由に使用できる場合は、DBAを関与させます。
外部キー制約とカスケード削除を使用する必要があります。これにより、トリガーなどが不要になります。
特別なdba_objectsテーブルをクエリできます:</ p>
DECLARE
X NUMBER;
BEGIN
SELECT COUNT(*) INTO X FROM DBA_OBJECTS WHERE OBJECT_TYPE = 'TRIGGER' AND OBJECT_NAME = 'YOUR_TRIGGER_NAME_HERE';
IF X = 0 THEN
--Trigger doesn't exist, OK to delete...
END IF;
END;
select * from Tab where Tname = "TABLENAME"
このクエリが行を返す場合、テーブルは存在します。そうでない場合は存在しません。