【问题标题】:Deleting a row with inner join使用内连接删除一行
【发布时间】:2017-11-11 13:48:41
【问题描述】:

我创建了两个表,simplecmetscommentors,并将它们与INNER JOIN 连接起来。

  • Simplecmets 是每个评论者的详细信息,包括他们的评论、reg_date、commentorid 等...
  • Commentors 是评论者的个人信息,包含以下列:id、name、email..

我已成功加入它们,但我发现很难从加入的表中删除。

我想让它像这样的逻辑:

  1. 如果评论者的最后一行名为 -- 假设为 A-- 然后从表中删除他/她的评论详细信息和 A 本人。

  2. 否则如果 A 多次发表评论,使用不同的 cmets,请删除他/她的评论详细信息,但保留他/她的个人信息,因为 A 有其他 cmets。 p>

这就是我的做法:

if (!empty($_POST["delete"]))
{
    foreach ($_POST["delete"] as $key => $value) 
    {
        $resultid = $conn->query("SELECT commentorid FROM `simplecomments` WHERE id=".$value);
        $rowid = $resultid->fetch_assoc();

        $outputdelete = $rowid["name"] . " has been deleted" . "<br>";

        $deletedname = $deletedname.$outputdelete;
        $RES = mysql_num_rows($resultid);
        $counter = 0;
            while($row = $RES)
            {
               //IF IT'S LAST ROW, DELETE COMMENTOR AND HIS/HER COMMENTDETAILS 
                if(++$counter == $results) {
                    $resultid = $conn->query("DELETE FROM `commentor`");
                }
                //ELSE JUST DELETE HIS/HER COMMENTDETAILS, LET HIS/HER INFO REMAIN
                else{
                    $resultid = $conn->query("DELETE FROM `simplecomments` WHERE id=".$value);
                } 
            }
    }

}

但是代码不起作用。我收到一个错误:

警告:mysql_num_rows() 期望参数 1 是资源 [..]...

【问题讨论】:

  • 请发布您获得的结果以及您期望获得的结果
  • @BrianDewhirst 我得到一个错误..“警告:mysql_num_rows() 期望参数 1 是资源,”..我在最后两段中的问题中说明了我想要它的方式..
  • 首先将mysql_num_rows 更改为mysqli_num_rows,然后重试并检查mysqli_error($conn) 查询中的错误。
  • @MAA ...我为您提供了解决方案,但现在我对逻辑感到困惑,尤其是(++$counter == $results)$RES 是否被错误地放在 $result 中?请显示一些行来说明您的示例。您是否只想删除评论者 cmets 的最新评论?并且只删除only 一条评论的评论者?

标签: php mysql sql join


【解决方案1】:

考虑使用子查询条件运行 DELETE...INNER JOINDELETE,并避免使用 if/else 进行 PHP 查询获取循环,因为逻辑似乎如下:

  1. 如果评论者只有一条评论,则删除他/她的个人资料和 cmets
  2. 如果评论者有多个(即不止一个)cmets,则仅删除评论者的 cmets。

是的,所有三个DELETE 可以在所有 id 上同时运行,因为互斥条件位于前两个和最后一个之间。因此,前两个影响行或最后一个影响每次迭代的行。不受影响的将从任一表中删除零行。

另外,simplecmets 记录首先被删除,因为该表可能具有与 commentor 的外键约束,因为它是一对多的关系。最后,下面假设 comment id 被传递到循环中(不是 commentor id)。

PHP (使用参数化,假设$conn是mysqli连接对象)

foreach ($_POST["delete"] as $key => $value) {

   // DELETE COMMENTS AND THEN PROFILE FOR COMMENTORS WITH ONE POST    
   $sql = "DELETE FROM `simplecomments` s 
           WHERE s.id = ?
             AND (SELECT COUNT(*) FROM `simplecomments` sub
                  WHERE sub.commentorid = s.commentorid) = 1";
   $stmt = $conn->prepare($sql);
   $stmt->bind_param("i", $value);
   $stmt->execute();
   $stmt->close();

   $sql = "DELETE c.* FROM `simplecomments` c 
           INNER JOIN `simplecomments` s ON s.commentorid = c.id
           WHERE s.id = ?
             AND (SELECT COUNT(*) FROM `simplecomments` sub
                  WHERE sub.commentorid = s.commentorid) = 1";
   $stmt = $conn->prepare($sql);
   $stmt->bind_param("i", $value);
   $stmt->execute();
   $stmt->close();


   // DELETE COMMENTS FOR COMMENTORS WITH MULTIPLE POSTS BUT KEEP PROFILE
   $sql = "DELETE FROM `simplecomments` s
           WHERE s.id = ?
             AND (SELECT COUNT(*) FROM `simplecomments` sub
                  WHERE sub.commentorid = s.commentorid) > 1";    
   $stmt = $conn->prepare($sql);
   $stmt->bind_param("i", $value);
   $stmt->execute();
   $stmt->close();
}

或者,对于 DRY-er 方法,在数组中循环 SQL 语句:

$sqls = array(
           0 => "DELETE FROM `simplecomments` s WHERE s.id = ? AND (SELECT COUNT(*) FROM `simplecomments` sub WHERE sub.commentorid = s.commentorid) = 1",
           1 => "DELETE c.* FROM `simplecomments` c INNER JOIN `simplecomments` s ON s.commentorid = c.id WHERE s.id = ? AND (SELECT COUNT(*) FROM `simplecomments` sub WHERE sub.commentorid = s.commentorid) = 1",
           2 => "DELETE FROM `simplecomments` s WHERE s.id = ? AND (SELECT COUNT(*) FROM `simplecomments` sub WHERE sub.commentorid = s.commentorid) > 1"
        );

foreach ($_POST["delete"] as $key => $value) {
   foreach($sqls as $sql) {
       $stmt = $conn->prepare($sql);
       $stmt->bind_param("i", $value);
       $stmt->execute();
       $stmt->close();
   }
}

【讨论】:

  • 非常感谢您,谢谢!但是,c 代表评论者,s 代表 simplecmets 和 sub?
  • 太棒了!乐意效劳。是的,这些字母是实际表的表别名,以帮助缩短查询并帮助在使用相同表的子查询和外部查询之间建立关联。
猜你喜欢
  • 2012-07-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-02
  • 1970-01-01
  • 2013-01-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多