【问题标题】:Can't delete multiple rows from MySQL table in a loop无法在循环中从 MySQL 表中删除多行
【发布时间】:2013-03-06 15:48:34
【问题描述】:

我正在尝试使用 php 的 PDO 对象从 mySQL 表中删除与一对条件匹配的所有行。我不知道为什么它不起作用:

//This deletes all comments for a given post;
//Querying database for existent comments on that post;
$this->query = $this->db->query(
"SELECT cid 
FROM comments
WHERE id = '$html_data->id' AND pid = '$html_data->pid'"
);
//Fetching results into an array;
$this->rows = $this->query->fetchAll(PDO::FETCH_ASSOC);
//Deleting each comment on that post;
foreach ($this->rows as $this->row) {
    $this->db->exec(
    "DELETE from comments 
    WHERE cid = '$this->row['cid']'"
    );
};
//Deleting the post itself;
$this->db->exec(
"DELETE from posts 
WHERE id = '$html_data->id' AND pid = '$html_data->pid'"
);

//Deleting the post itself 有效,但 foreach 循环内的部分由于某种原因不起作用。为了调试,我在循环中添加了以下内容:

echo "WHERE cid = '{$this->row['cid']}'";

它按预期返回:

WHERE cid = '1'
WHERE cid = '2'

因此,获取的数据不是问题。我也试过了

WHERE id = '$html_data->id' AND pid = '$html_data->pid' AND cid = '$this->row['cid']'"

而不是只使用cid,它也不起作用。回声它返回,正如预期的那样:

WHERE id = '1' AND pid = '1' AND cid = '1'
WHERE id = '1' AND pid = '1' AND cid = '2'

是的,我检查了comments 表,我要删除的idpidcid 与正在回显的那些匹配。

【问题讨论】:

  • 只需 var_dump() 查询,查找双引号或单引号,因为有时它们不存在或只是 var_dump() 查询,然后转到 phpmyadmin 并将查询粘贴到查询选项卡它会显示你有什么样的错误,还有DELETE FROM table_name WHERE id=1已经循环遍历表中的所有记录
  • 因此,您的问题与 mysqli 无关,而与基本的 PHP 语法(以及 $this 关键字的不当使用)有关。另一个过于本地化的问题会污染网站
  • 显然我不知道问题出在哪里,对我来说,在循环中使用 PDO/mySQL 是个问题,因为外面的代码几乎相同并且可以正常工作。不过下次我会考虑使用 Code Review 或其他网站,谢谢您的意见。

标签: php mysql pdo delete-row corresponding-records


【解决方案1】:

因此,解决此问题的更好方法是使用准备好的语句并从查询中获取变量。这样,您既可以解决此问题,也可以修复您现在遇到的安全问题(SQL 注入)...

这是您的代码转换为高效的预处理语句:

$stmt= $this->db->prepare(
    "SELECT cid 
    FROM comments
    WHERE id = ? AND pid = ?"
);
$this->query = $stmt->execute(array($html_data->id, $html_data->pid));

$this->rows = $this->query->fetchAll(PDO::FETCH_ASSOC);

$deleteStmt = $this->db->prepare(
    "DELETE from comments 
    WHERE cid = ?"
);
foreach ($this->rows as $row) {
    $deleteStmt->execute(array($row['cid']));
};

//Deleting the post itself;
$stmt = $this->db->prepare(
    "DELETE FROM posts
    WHERE id = ? AND pid = ?"
);
$stmt->execute(array($html_data->id, $html_data->pid));

但是,您可以进一步清理它。处理这个问题的最好方法是使用外键。例如,让我们从 cmets 表的 pid 到帖子 id 字段创建一个外键。

CREATE TABLE posts (
    id   INT,
    name VARCHAR(35),
    PRIMARY KEY (`id`)
) ENGINE = InnoDB;

CREATE TABLE comments (
    id   INT,
    pid  INT,
    name VARCHAR(35),
    PRIMARY KEY (`id`),
    CONSTRAINT `posts_id`
    FOREIGN KEY `posts_id` (`pid`)
    REFERENCES `posts` (`id`)
    ON DELETE CASCADE
    ON UPDATE CASCADE
) ENGINE = InnoDB

这里的美妙之处在于,您在上面的大代码块简化为:

$stmt = $this->db->prepare(
    "DELETE FROM posts
    WHERE id = ? AND pid = ?"
);
$stmt->execute(array($html_data->id, $html_data->pid));

当您删除评论时,约束(外键)将自动级联删除以删除 cmets(因为如果没有,则会有无效的约束)...

【讨论】:

    【解决方案2】:

    应该是

    $this->db->exec(
    "DELETE from comments 
    WHERE cid = '$this->row[cid]'"
    );
    

    或者你也可以使用

    $this->db->exec(
    "DELETE from comments 
    WHERE cid = '{$this->row['cid']}'"
    );
    

    【讨论】:

    • 您的第二种方法有效,谢谢。这很奇怪,因为下面的查询 //Deleting the post itself 工作正常,我不需要使用 {}。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-28
    • 2010-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-21
    • 1970-01-01
    相关资源
    最近更新 更多