Mysql

MySQL:如果外鍵約束,更新而不是刪除?

  • September 2, 2013

我有一個奇怪的問題。我知道插入重複鍵更新。我的問題是,由於外鍵約束而失敗的刪除是否有類似的東西?

例如:

從 table1 中刪除 value=‘something’;

但是,table2 有一個外鍵,它取決於我要在 table1 中刪除的值,因此刪除失敗。我想做這樣的事情:

從表 1 中刪除,其中外鍵上的 value=‘something’ 失敗 update some_other_value=‘something else’;

我知道這看起來很奇怪,但我有充分的理由這樣做(無需詳細說明,它與版本化歷史數據有關,如果在其他地方引用了值,則無法銷毀這些數據。)我可以想當然,如何使用多個查詢來做到這一點,但如果可以的話,我想在一個查詢中做到這一點。我很確定這是不可能的,但我想在放棄之前問一下:)

謝謝!

你不能直接這樣做,因為沒有辦法(我能想到)交替地UPDATEDELETE從同一個查詢中……通常一個查詢只能做一種類型的CRUD操作(ON DUPLICATE KEY UPDATE這是一個例外)。

但是,您可以使用儲存過程使其“感覺像”單個查詢,您可以在其中CONTINUE HANDLER為您預期的外鍵錯誤設置一個。處理程序將擷取錯誤並可用於設置一個變數,您可以測試該變數以查看您是否遇到錯誤,因此還需要嘗試更新查詢。

DELIMITER $$

DROP PROCEDURE IF EXISTS delete_or_update $$
CREATE PROCEDURE delete_or_update (IN input_value INT)
BEGIN

 DECLARE hit_fk_error TINYINT DEFAULT 0;
 DECLARE deleted_row_count INT DEFAULT NULL;
 DECLARE updated_row_count INT DEFAULT NULL;

 -- 1451 is probably the error code that will be generated
 -- Cannot delete or update a parent row: a foreign key constraint fails (%s)
 -- otherwise, you may need to substitute the correct error code in the next line

 DECLARE CONTINUE HANDLER FOR 1451 SET hit_fk_error = TRUE;

 DELETE FROM parent_table WHERE tested_column = input_value; /* arg to the stored proc */
 SET deleted_row_count = ROW_COUNT();

 IF (hit_fk_error = TRUE) THEN
   UPDATE parent_table SET some_other_value = 'something_else'
    WHERE tested_column = input_value;
   SET updated_row_count = ROW_COUNT();
 END If;

 SELECT deleted_row_count, updated_row_count, hit_fk_error;

END $$

DELIMITER ;

這將嘗試刪除;如果遇到外鍵錯誤,它將嘗試更新(並且外鍵錯誤將被抑制)。該過程將返回一個記錄集,其中包含每個查詢影響的行數以及是否發生外鍵錯誤。如果“input_value”不是一個INTWHERE子句更複雜,則需要相應地修改結構。

我在這裡看到的潛在問題是,如果 where 子句太寬泛,並且匹配一些會導致外鍵錯誤的行和其他不會導致外鍵錯誤的行,那麼查詢將不會單獨處理這些行。這可以通過一個更複雜的過程來完成,該過程使用游標來查找 where 子句中的行,並在辨識它們之後嘗試通過主鍵單獨刪除或更新它們。這種方法效率較低,但更精確。

引用自:https://dba.stackexchange.com/questions/49077