多表删除MySQL通过PHP

时间:2013-12-04 15:35:52

标签: php mysql

我正在制作一个简单的数据库,用作电子商务网站的模拟示例。我需要做的一件事是使用PHP从数据库中删除记录。我可以删除用户名或订单等。但是,当我尝试一次性完成这些操作时,我正在搞砸了。我想要发生的是删除有关用户的所有信息。示例:用户信息,装运信息,账单信息,信用卡信息以及与特定用户有关的任何其他信息。我的表格如下。

mysql> SHOW columns FROM shirt_billing_addresses; 
 +----------------------------+--------------+------+-----+---------+----------------+
 | Field                      | Type         | Null | Key | Default | Extra          |
 +----------------------------+--------------+------+-----+---------+----------------+
 | shirt_billing_addresses_id | mediumint(9) | NO   | PRI | NULL    | auto_increment | 
 | house                      | mediumint(9) | NO   |     | NULL    |                | 
 | street                     | varchar(100) | NO   |     | NULL    |                | 
 | city                       | varchar(100) | NO   |     | NULL    |                | 
 | state                      | char(2)      | NO   |     | NULL    |                | 
 | zip                        | char(5)      | NO   |     | NULL    |                | 
 +----------------------------+--------------+------+-----+---------+----------------+
 6 rows in set (0.01 sec)

 mysql> SHOW columns FROM shirt_credit_cards; 
 +-----------------------+--------------+------+-----+---------+----------------+
 | Field                 | Type         | Null | Key | Default | Extra          |
 +-----------------------+--------------+------+-----+---------+----------------+
 | shirt_credit_cards_id | mediumint(9) | NO   | PRI | NULL    | auto_increment | 
 | shirt_users_id        | mediumint(9) | NO   | MUL | NULL    |                | 
 | type                  | varchar(30)  | NO   |     | NULL    |                | 
 | no                    | char(16)     | NO   |     | NULL    |                | 
 | security_code         | char(3)      | NO   |     | NULL    |                | 
 +-----------------------+--------------+------+-----+---------+----------------+
 5 rows in set (0.04 sec)

 mysql> SHOW columns FROM shirt_orders; 
 +-----------------------------+--------------+------+-----+---------+----------------+
 | Field                       | Type         | Null | Key | Default | Extra          |
 +-----------------------------+--------------+------+-----+---------+----------------+
 | shirt_orders_id             | int(11)      | NO   | PRI | NULL    | auto_increment  
 | order_total                 | double(6,2)  | NO   |     | NULL    |                |
 | payment_date                | datetime     | NO   |     | NULL    |                |
 | shirt_credit_cards_id       | mediumint(9) | NO   | MUL | NULL    |                |
 | shirt_shipping_addresses_id | mediumint(9) | NO   | MUL | NULL                    
 | shirt_billing_addresses_id  | mediumint(9) | NO   | MUL | NULL    |                
 | shirt_shipping_methods_id   | tinyint(4)   | NO   | MUL | NULL    |                
+-----------------------------+--------------+------+-----+---------+----------------+
 7 rows in set (0.02 sec)

 mysql> SHOW columns FROM shirt_shipping_addresses; 
 +-----------------------------+--------------+------+-----+---------+----------------+
 | Field                       | Type         | Null | Key | Default | Extra          |
 +-----------------------------+--------------+------+-----+---------+----------------+
 | shirt_shipping_addresses_id | mediumint(9) | NO   | PRI | NULL    | auto_increment  
| house                       | mediumint(9) | NO   |     | NULL    |                | 
| street                      | varchar(100) | NO   |     | NULL    |                | 
| city                        | varchar(100) | NO   |     | NULL    |                | 
| state                       | char(2)      | NO   |     | NULL    |                | 
| zip                         | char(5)      | NO   |     | NULL    |                | 
+-----------------------------+--------------+------+-----+---------+----------------+
6 rows in set (0.03 sec)

mysql> SHOW columns FROM shirt_users; 
+----------------+--------------+------+-----+---------+----------------+
| Field          | Type         | Null | Key | Default | Extra          |
+----------------+--------------+------+-----+---------+----------------+
| shirt_users_id | mediumint(9) | NO   | PRI | NULL    | auto_increment | 
| first_name     | varchar(30)  | NO   |     | NULL    |                | 
| last_name      | varchar(30)  | NO   |     | NULL    |                | 
| email          | varchar(30)  | NO   |     | NULL    |                | 
| user_id        | varchar(30)  | NO   |     | NULL    |                | 
| password       | char(40)     | NO   |     | NULL    |                | 
+----------------+--------------+------+-----+---------+----------------+
6 rows in set (0.03 sec)

mysql> SHOW columns FROM shirt_users_types;         
+----------------------+--------------+------+-----+---------+----------------+
| Field                | Type         | Null | Key | Default | Extra          |
+----------------------+--------------+------+-----+---------+----------------+
| shirt_users_types_id | int(11)      | NO   | PRI | NULL    | auto_increment | 
| shirt_users_id       | mediumint(9) | NO   | MUL | NULL    |                | 
| shirt_types_id       | smallint(6)  | NO   | MUL | NULL    |                | 
| shirt_orders_id      | int(11)      | NO   | MUL | NULL    |                | 
| type_quantity        | smallint(6)  | NO   |     | NULL    |                | 
| type_total           | double(6,2)  | NO   |     | NULL    |                | 
+----------------------+--------------+------+-----+---------+----------------+
6 rows in set (0.03 sec)

我的PHP代码如下:

@mysqli_query($link, "SET AUTOCOMMIT=0");
    $select_sui = "SELECT 
    shirt_users.shirt_users_id, 
    shirt_users_types.shirt_users_types_id, 
    shirt_orders.shirt_orders_id, 
    shirt_shipping_addresses.shirt_shipping_addresses_id, 
    shirt_billing_addresses.shirt_billing_addresses_id, 
    shirt_credit_cards.shirt_credit_cards_id 
    from
    shirt_users, 
    shirt_users_types, 
    shirt_orders, 
    shirt_shipping_addresses, 
    shirt_billing_addresses, 
    shirt_credit_cards
    where
    shirt_users.shirt_users_id = shirt_users_types.shirt_users_id and
    shirt_users_types.shirt_orders_id = shirt_orders.shirt_orders_id and
    shirt_orders.shirt_shipping_addresses_id = shirt_shipping_addresses.shirt_shipping_addresses_id and
    shirt_orders.shirt_billing_addresses_id = shirt_billing_addresses.shirt_billing_addresses_id and
    shirt_orders.shirt_credit_cards_id = shirt_credit_cards.shirt_credit_cards_id and
    shirt_users.shirt_users_id = $shirt_users_id";

唯一的问题是此查询将返回一个空集,除非所有表中都包含正确的信息。这是一个问题,因为如果用户尚未订购任何项目,但我想从数据库中删除它们,它将不允许我。任何有关此事的帮助将不胜感激。

1 个答案:

答案 0 :(得分:2)

您必须使用LEFT JOIN链接表格(MySQL doc)。

SELECT [...]
    FROM shirt_users 
    LEFT JOIN shirt_users_types ON shirt_users.shirt_users_id = shirt_users_types.shirt_users_id
    LEFT JOIN shirt_orders ON shirt_users_types.shirt_orders_id = shirt_orders.shirt_orders_id
    LEFT JOIN shirt_shipping_addresses ON shirt_orders.shirt_shipping_addresses_id = shirt_shipping_addresses.shirt_shipping_addresses_id
    LEFT JOIN shirt_billing_addresses ON shirt_orders.shirt_billing_addresses_id = shirt_billing_addresses.shirt_billing_addresses_id
    LEFT JOIN shirt_credit_cards ON shirt_orders.shirt_credit_cards_id = shirt_credit_cards.shirt_credit_cards_id
    WHERE
    shirt_users.shirt_users_id = $shirt_users_id

使用此功能,即使其他表中没有链接记录,您也可以加载shirt_users

编辑删除记录

如果只想在一个请求中删除所有表,则必须使用与第一次尝试完全相同的语法(通过SELECT替换DELETE语句)。你会得到同样的问题(它只会删除每个表中都有链接记录而不是空的记录)。

方法1:

注意:您的数据库必须支持外键(例如,MyISAM不支持它,但InnoDB支持外键)。

如果您在应用中始终需要删除所有链接的记录,则可以使用此方法。

实现这一目标的最美妙方法是在你的关系中添加ON DELETE CASCADE约束:

-- Drop the old constraint ("fk_test" must be replace by your constraint name)
ALTER TABLE shirt_users_types DROP FOREIGN KEY `fk_test`;

-- Create the new with ON DELETE
ALTER TABLE shirt_users_types
   ADD CONSTRAINT `fk_test`
   FOREIGN KEY (`shirt_users_id` )
   REFERENCES `shirt_users` (`shirt_users_id` )
   ON DELETE CASCADE;

当您删除shirt_users条目时,shirt_users_types中的所有关联记录。

简而言之,使用ON DELETE CASCADE,每次删除父元素(关系的One侧)时,所有子项(关系的Many侧)或者包含列<related_record>_id的表格也将被自动删除。

方法2:

如果您的关系可以为空(例如,如果shirt_users_types.shirt_orders_id可以为null),或者您的数据库架构不允许使用ON DELETE CASCADE删除所有需要的记录。

您可以使用与DELETE的关系删除多个shirt_users的记录,以便检索每个链接表中的记录。 (有关DELETE的正确语法,请参阅MySQL docs)。

在您的代码中,您的唯一标识符为$shirt_users_id,因此您必须首先删除与shirt_users没有直接关联的表格,然后通过表格{{返回您的关系来完成1}}。

如果您没有按正确的顺序删除记录,您将无法删除所需的全部内容。

例如,对于问题中描述的架构,如果您在shirt_users之前删除shirt_orders中的记录,则您将无法再使用shirt_shipping_addresses检索送货地址,因为$shirt_users_id由于与shirt_shipping_addresses的关系,因此与shirt_users相关联。

因此,您当前架构的正确顺序是(不需要在上面的列表的同一行上订购表):

  • shirt_shipping_addresses / shirt_billing_addresses
  • shirt_orders / shirt_credit_cards / shirt_users_types
  • shirt_users

由于外键,您可能会出现shirt_orders错误。在这种情况下,您可以使用contraint fails进行删除(这是最佳做法)或禁用外键检查。

TRANSACTION