2015-11-19 81 views
0

我剛剛用PHP完成了我的第一個網站,而現在我剛剛注意到了一個問題。我的很多動態內容都與其他表格中的行「鏈接」。所以當其他表中的行被刪除時,它顯然會給我一個錯誤。例如,我有一個表「book_groups」,用於從表「books」,「hosts」和「locations」中提取數據。因此,在查詢某個book_group後,我根據與該組一起存儲的book_id,host_id和location_id對其他表進行更多查詢。鏈接MySQL數據庫中的行並使用PHP查詢

我顯然沒有足夠的計劃。因爲如果一本書被意外刪除然後重新添加,該ID將會改變並且會被打破。

我的問題是,現在解決這個問題的最好方法是什麼,我已經完成了所有工作?我可以回到每個查詢並添加一個if($ query_result!= false)來查看該行是否仍然存在。但男人有很多疑問,因爲我有很多不同類型的組和相關表。

爲了將來的參考,是否有更好的方式來鏈接MySQL中的表格,而不是隻存儲相關表格行的ID?

+0

你正確地聯繫起來。一種解決方案是在代碼中有一個規定,如果一本書被刪除,那麼依賴該書的book_groups也會被刪除。許多MVC框架都具有開箱即用的解決方案,例如Rails依賴的::destroy(我知道你在使用PHP--這只是想到的第一個例子) – jackel414

+0

對我來說似乎是一對多映射。我猜想INNER JOIN查詢的時間太晚了?我認爲「book_group」應該只是與書相關聯的id列表,然後通過group_id進行INNER JOIN,您只能獲取存儲在books表中的書籍,稍後可以修剪book_group。 – DataHerder

+0

我不想刪除任何組。我只想要能夠改變哪本書目前與之相關聯。我對MVC框架一無所知(這對我來說都是新的),但我會研究它。 – Bobby

回答

0

您的主題是參照完整性。在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操作被取消。

您可以通過MySqlhere瞭解參考完整性。

您可以在PHP中做類似的事情,但在通過其他工具(如phpAdmin)連接時,可能會繞過此類代碼。觸發器的優勢在於它們獨立於連接的位置執行,並且它們在與原理操作相同的事務中執行。缺點是你有另一層代碼來維護,旁邊的php代碼。而且php代碼必須知道這些觸發器可能具有的其他表的副作用。

的一些想法做一個在phpbook受控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... 
+0

看起來第二個解決方案可能會起作用。但是我希望所有的數據庫查詢都可以通過我用PHP創建的CMS來實現。我可以以某種方式在PHP中進行該查詢,並告訴用戶在刪除之前哪些記錄依然依賴它,然後如果需要提示繼續嗎? – Bobby

+0

當然,你會做一個'mysqli_query'來計算'books_query'中具有相同id的記錄數,然後看它是否非零,提供一個頁面,用戶必須提交它們的確定,如果你的' php'看到確認參數存在,你執行刪除。 – trincot

+0

我已經添加了一些這樣的'php'代碼的跡象。沒有測試過,只是爲了給出一個想法。 – trincot