2015-11-19 105 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