You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ON DELETE CASCADE在MariaDB生效但PHP PDO中失效问题求助

PDO执行DELETE时ON DELETE CASCADE未触发,仅删除主表记录

我需要删除plats表(主表)的一条记录,并通过外键的ON DELETE CASCADE规则同步删除plats_categories表(关联表)的匹配记录。直接在MariaDB中执行DELETE语句时,级联删除正常生效,两张表的对应记录都会被删除;但用PHP PDO的prepare和execute方法执行时,只有plats表的记录被删除,plats_categories的对应记录残留,造成数据库冗余。

表结构

-- 主表 plats
CREATE TABLE plats(
id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, 
title VARCHAR(200) NOT NULL, 
description VARCHAR(300) NOT NULL, 
price INTEGER NOT NULL) ENGINE=InnoDB;

-- 分类表 category1
CREATE TABLE category1(
c1_id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, 
c1_type VARCHAR(255) NOT NULL) ENGINE=InnoDB;

-- category2结构与category1一致
CREATE TABLE category2(
c2_id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, 
c2_type VARCHAR(255) NOT NULL) ENGINE=InnoDB;

-- 关联表 plats_categories
CREATE TABLE plats_categories(
pc_id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, 
plats_id INTEGER NOT NULL, 
category1_id INTEGER NOT NULL, 
category2_id INTEGER NOT NULL, 
FOREIGN KEY(plats_id) REFERENCES plats(id) ON DELETE CASCADE ON UPDATE CASCADE,
FOREIGN KEY(category1_id) REFERENCES category1(c1_id) ON DELETE CASCADE ON UPDATE CASCADE, 
FOREIGN KEY(category2_id) REFERENCES category2(c2_id) ON DELETE CASCADE ON UPDATE CASCADE) ENGINE=InnoDB;

PHP模型代码(delete-course.php)

<?php

require_once __DIR__ .'/../db.php';
$getIdCourse = $_GET['id'];
$courses = $pdo->prepare('SELECT * FROM plats WHERE id = ?');
$courses->execute(array($getIdCourse));
if ($courses->rowCount() > 0)
{
    $deleteCourse = $pdo->prepare('DELETE FROM plats WHERE id = ?');
    $deleteCourse->execute(array($getIdCourse));
}else
{
    $_SESSION['flash']['danger'] = 'Aucun plat n\'a été trouvé';
}

PHP控制器代码

<?php
session_start();

if (isset($_GET['id']) && !empty($_GET['id']))
{
    require __DIR__ .'/../../../model/menus-carte/delete-course.php';
    $_SESSION['flash']['success'] = 'Le plat a bien été supprimé';
    header('Location: admin-courses.php');
}else
{
    $_SESSION['flash']['danger'] = 'L\'identifiant du plat n\'a pas été récupéré';
}

可能的原因及解决方法

  • 检查PDO自动提交设置:查看db.php中的PDO连接配置,如果设置了PDO::ATTR_AUTOCOMMIT => false,删除操作后需要手动执行$pdo->commit();,级联操作才会触发。
  • 验证外键约束有效性:执行SHOW CREATE TABLE plats_categories;,确认plats_id的外键定义包含ON DELETE CASCADE,且表引擎为InnoDB(MyISAM不支持外键)。
  • 开启PDO错误模式:在db.php的PDO初始化代码中添加$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);,捕获隐藏的外键相关错误。
  • 确认数据类型匹配:检查plats.id和plats_categories.plats_id的数据类型完全一致(均为INTEGER),类型不匹配会导致外键约束失效。
  • 排查事务冲突:如果代码其他地方开启了事务但未正确提交/回滚,会影响当前删除操作的级联执行,需检查相关事务逻辑。

内容的提问来源于stack exchange,提问作者MAX

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 08:19:57