您的主題是參照完整性。在MySQL中,您可以通過數據庫觸發器強制執行此類完整性。
例如,您可以定義執行delete
發生在一個父記錄之前觸發:
CREATE TRIGGER trg_books_bef_delete
BEFORE DELETE
ON books
FOR EACH ROW
BEGIN
DELETE FROM book_groups WHERE book_id = old.book_id;
END;
這個特殊的觸發器將在book_groups
是指被刪除book
記錄刪除任何相關記錄。
您可以決定採取不同的響應方式,並且在具有相關記錄的book
記錄被刪除時引發錯誤。由於從MySQL 5.5,你可以這樣做:
CREATE TRIGGER trg_books_bef_delete
BEFORE DELETE
ON books
FOR EACH ROW
BEGIN
IF (SELECT COUNT(*) FROM book_groups WHERE book_id = old.book_id) > 0
THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Foreign Key Constraint Violated!';
END IF;
END;
在這種情況下,如果book_groups
記錄被發現,是指book
記錄被刪除,狠狠地拋出異常,而delete
操作被取消。
您可以通過MySql
here瞭解參考完整性。
您可以在PHP
中做類似的事情,但在通過其他工具(如phpAdmin
)連接時,可能會繞過此類代碼。觸發器的優勢在於它們獨立於連接的位置執行,並且它們在與原理操作相同的事務中執行。缺點是你有另一層代碼來維護,旁邊的php
代碼。而且php
代碼必須知道這些觸發器可能具有的其他表的副作用。
的一些想法做一個在php
book
受控delete
:
$confirmed = false;
if (isset($_POST["confirm"])) {
$confirmed = true;
}
$book_id = $_POST["book_id"]);
$con = mysqli_connect(...);
// Check for dependent records that would also be deleted:
if ($stmt = mysqli_prepare($con,
"SELECT COUNT(*) AS cnt FROM book_groups WHERE book_id = ?")) {
mysqli_stmt_bind_param($stmt, "i", $book_id);
mysqli_stmt_execute($stmt);
mysqli_stmt_bind_result($stmt, $cnt);
mysqli_stmt_fetch($stmt);
mysqli_stmt_close($stmt);
if ($cnt > 0 && !$confirmed) {
?>
<html>
<body>
<form action="" method="post">
<input type="hidden" name="book_id" value="<?=$book_id?>"/>
This book is categorised in groups,
are you sure to delete that information?
<input type="submit" value="confirm" name="confirm"/>
</form>
</body>
</html>
<?php
exit;
}
}
// continue to delete book below...
你正確地聯繫起來。一種解決方案是在代碼中有一個規定,如果一本書被刪除,那麼依賴該書的book_groups也會被刪除。許多MVC框架都具有開箱即用的解決方案,例如Rails依賴的::destroy(我知道你在使用PHP--這只是想到的第一個例子) – jackel414
對我來說似乎是一對多映射。我猜想INNER JOIN查詢的時間太晚了?我認爲「book_group」應該只是與書相關聯的id列表,然後通過group_id進行INNER JOIN,您只能獲取存儲在books表中的書籍,稍後可以修剪book_group。 – DataHerder
我不想刪除任何組。我只想要能夠改變哪本書目前與之相關聯。我對MVC框架一無所知(這對我來說都是新的),但我會研究它。 – Bobby