简体   繁体   English

PHP,PDO,MySQL和InnoDB,如何使用FK更新/删除记录?

[英]PHP, PDO, MySQL & InnoDB, how to update/delete records with FK?

I've read similar questions but there aren't very detailed explanations on using ON DELETE and ON UPDATE so i'm having trouble understanding that and also what are the correct procedures to update your database when you want to remove or update a record with FK constraint but not delete the records in other tables when it was referenced, but set those references to null or 0 or something in the other tables. 我已经读过类似的问题,但是关于使用ON DELETE和ON UPDATE的信息并没有非常详细的解释,所以我很难理解,当您要删除或更新记录时,有什么正确的步骤来更新数据库? FK约束,但在引用时不删除其他表中的记录,而是将这些引用设置为null或0或其他表中的内容。

Background 背景

I'm trying to create a library of functions for this database (for an e-cart system) so that the database can be managed by an admin (like a CMS). 我正在尝试为此数据库(用于电子购物车系统)创建功能库,以便可以由管理员(如CMS)管理该数据库。

I chose InnoDB engine to make use of foreign keys and transactions. 我选择了InnoDB引擎来利用外键和事务。

I'm also using PHP PDO objects rather than the standard mysql_ -functions to make use of parametrized queries. 我还使用PHP PDO对象而不是标准的mysql_来使用参数化查询。

This is the SQL creation code for these tables: 这是这些表的SQL创建代码:

# TBL_MENU_CATEGORY

DROP TABLE IF EXISTS tbl_menu_category;
CREATE TABLE tbl_menu_category(
    id INT NOT NULL AUTO_INCREMENT,
    PRIMARY KEY(id),
    name VARCHAR(50)
) ENGINE = InnoDB;

# TBL_PRODUCT_CATEGORY

DROP TABLE IF EXISTS tbl_product_category;
CREATE TABLE tbl_product_category(
    id INT NOT NULL AUTO_INCREMENT,
    PRIMARY KEY(id),
    name VARCHAR(50)
) ENGINE = InnoDB;


# TBL_MENU_CAT_BASKET

DROP TABLE IF EXISTS tbl_menu_cat_basket;
CREATE TABLE tbl_menu_cat_basket(
    menu_id INT,
    FOREIGN KEY(menu_id) REFERENCES tbl_menu_category(id),
    cat_id INT,
    FOREIGN KEY(cat_id) REFERENCES tbl_product_category(id)
) ENGINE = InnoDB;


# TBL_PRODUCT_CAT_BASKET

DROP TABLE IF EXISTS tbl_product_cat_basket;
CREATE TABLE tbl_product_cat_basket(
    cat_id INT,
    FOREIGN KEY(cat_id) REFERENCES tbl_product_category(id),
    product_id INT,
    FOREIGN KEY(product_id) REFERENCES tbl_product(id)
) ENGINE = InnoDB;

This is a function in the library to add a Submenu to a Menu (Menu > Submenu > Product). 库中的一项功能是向菜单添加子菜单(菜单>子菜单>产品)。

function addSubmenu($menu_id, $sub_name) {
    $success = false;
    if ( dbTransaction() ) {
        $sql = "INSERT INTO tbl_product_cat(name) VALUES ('?');";
        dbQuery($sql, array($sub_name));
        $rows = dbRowsAffected();
        if ($rows == 1) {
            $cat_id = dbLastInsertId();
            $sql = "INSERT INTO tbl_menu_cat_basket(menu_id, cat_id) VALUES ('?','?');";
            dbQuery($sql, array((int)$menu_id, (int)$cat_id));
            $rows = dbRowsAffected();
            if ($rows == 1) {
                $success = true;
            }
        }
        if ($success)
            dbCommit();
            return "Add submenu successful.";
        else
            dbRollback();
            return "Add submenu failed.";
    }
}

The query is executed like this: 查询执行如下:

require_once "pdo.php"; # Creates PDO object '$db'
$query;

function dbQuery($sql, $data) {
    global $db, $query;
    $query = $db->prepare($sql);
    $query->execute($data);
}

# other PDO & PDOStatement methods like this
# (rowCount, lastInsertId, fetchAll, transaction-stuff).

Problems 问题

I'm not even sure if this is correct. 我什至不确定这是否正确。 Am I following the right path or doing things wrongly? 我是走正确的道路还是做错了事?

Now I'm stuck on creating similar functions for updating a record which also have foreign keys. 现在,我坚持创建类似的功能来更新也具有外键的记录。 I know that InnoDB will throw an error that the record can't be updated because it has references (I think?). 我知道InnoDB会引发错误,因为该记录具有引用(我认为?),所以无法更新该记录。

I need to know the correct procedure for updating records and the functions available to me for doing so. 我需要知道更新记录的正确过程以及为此可用的功能。

I want to know about ON DELETE and ON UPDATE constraints but I can't seem to find any good, newb-friendly tutorials (the MySQL docs are very unfriendly and don't even highlight syntax). 我想了解ON DELETE和ON UPDATE约束,但是我似乎找不到任何对新手友好的优秀教程(MySQL文档非常不友好,甚至不突出语法)。

What I want to do 我想做的事

When updating records I want to cascade the update so that all references are updated. 在更新记录时,我想级联更新,以便所有引用都被更新。

When deleting records I just want to delete the record that was deleted BUT any references to it can be reset instead (if a product category is deleted the products should NOT be deleted; if a product is deleted all orders with that product should NOT be deleted but the product value set to 0 or null) 在删除记录时,我只想删除已删除的记录,但是可以重设对该记录的任何引用(如果删除了产品类别,则不应删除产品;如果删除了产品,则不应删除该产品的所有订单但产品值设置为0或null)

How can I do this with ON DELETE and ON UPDATE -or- what procedures should I take to achieve what I want to do here? 我该如何使用ON DELETE和ON UPDATE来执行此操作-或-应该采取什么步骤来实现我在这里想要执行的操作?

Thank you for reading. 感谢您的阅读。

Specifying ON UPDATE CASCADE ON DELETE SET NULL in your foreign key specification should do the trick. 在外键规范中指定ON UPDATE CASCADE ON DELETE SET NULL应该可以解决问题。

For example, FOREIGN KEY(product_id) REFERENCES tbl_product(id) ON UPDATE CASCADE ON DELETE SET NULL . 例如, FOREIGN KEY(product_id) REFERENCES tbl_product(id) ON UPDATE CASCADE ON DELETE SET NULL Though I have to wonder where do you foresee situations where changing primary key values would make sense. 尽管我想知道您在哪里预见到更改主键值有意义的情况。

You might be interested in MySQL Workbench - it can help you design schemas visually and display corresponding DDL statements. 您可能对MySQL Workbench感兴趣-它可以帮助您直观地设计架构并显示相应的DDL语句。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM