使用内连接删除一行
Posted
技术标签:
【中文标题】使用内连接删除一行【英文标题】:Deleting a row with inner join 【发布时间】:2017-11-11 13:48:41 【问题描述】:我创建了两个表,simplecmets 和 commentors,并将它们与INNER JOIN
连接起来。
我已成功加入它们,但我发现很难从加入的表中删除。
我想让它像这样的逻辑:
如果评论者的最后一行名为 -- 假设为 A-- 然后从表中删除他/她的评论详细信息和 A 本人。
否则如果 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 是资源,”..我在最后两段中的问题中说明了我想要它的方式.. ***.com/questions/2973202/… 首先将mysql_num_rows
更改为mysqli_num_rows
,然后重试并检查mysqli_error($conn)
查询中的错误。
@MAA ...我为您提供了解决方案,但现在我对逻辑感到困惑,尤其是(++$counter == $results)
。 $RES 是否被错误地放在 $result 中?请显示一些行来说明您的示例。您是否只想删除评论者 cmets 的最新评论?并且只删除only 一条评论的评论者?
【参考方案1】:
考虑使用子查询条件运行 DELETE...INNER JOIN
和 DELETE
,并避免使用 if/else
进行 php 查询获取循环,因为逻辑似乎如下:
-
如果评论者只有一条评论,则删除他/她的个人资料和 cmets
如果评论者有多个(即不止一个)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? 太棒了!乐意效劳。是的,这些字母是实际表的表别名,以帮助缩短查询并帮助在使用相同表的子查询和外部查询之间建立关联。以上是关于使用内连接删除一行的主要内容,如果未能解决你的问题,请参考以下文章