2012-11-22 83 views
0

这个问题的顺序是我的previous Question需要更新删除一行的同一个表。使用连接或顺序哪个更新更快?

我可以使用存储过程而不是触发器或嵌套查询来编写两个解决方案。

两者都使用帮助函数my_signal(msg)

Employee表中删除员工的存储过程。

  • 拳头解决方案:在表中使用UPDATE行,无连接操作
CREATE PROCEDURE delete_employee(IN dssn varchar(64)) 
BEGIN 
    DECLARE empDesignation varchar(128); 
    DECLARE empSsn   varchar(64); 
    DECLARE empMssn  varchar(64); 
    SELECT SSN, designation, MSSN INTO empSsn, empDesignation, empMssn 
    FROM Employee 
    WHERE SSN = dssn; 

    IF (empSsn IS NOT NULL) THEN 
    CASE  
      WHEN empDesignation = 'OWNER' THEN 
       CALL my_signal('Error: OWNER can not deleted!'); 

      WHEN empDesignation = 'WORKER' THEN 
      DELETE FROM Employee WHERE SSN = empSsn;    

      WHEN empDesignation = 'BOSS' THEN 
       BEGIN 
        UPDATE Employee 
        SET MSSN = empMssn 
        WHERE MSSN = empSsn; 

       DELETE FROM Employee WHERE SSN = empSsn;     

       END; 
    END CASE; 
    ELSE 
       CALL my_signal('Error: Not a valid row!'); 
    END IF; 
END// 
  • 解决方法二:我建议在我以前的问题使用INNER JOIN
CREATE PROCEDURE delete_employee(IN dssn varchar(64)) 
BEGIN 
    DECLARE empDesignation varchar(128); 
    DECLARE empSsn   varchar(64); 
    DECLARE empMssn  varchar(64); 
     SELECT SSN, designation, MSSN INTO empSsn, empDesignation, empMssn 
     FROM Employee 
     WHERE SSN = dssn; 

    IF (empSsn IS NOT NULL) THEN 
     IF (empDesignation = 'OWNER') THEN 
     CALL my_signal('Error: OWNER can not deleted!'); 
     END IF; 

     UPDATE `Employee` A INNER JOIN `Employee` B ON A.SSN= B.MSSN 
     SET B.MSSN = A.MSSN WHERE A.SSN = empSsn; 

     DELETE FROM `Employee` WHERE SSN = empSsn; 
    ELSE 
     CALL my_signal('Error: Not a valid row!'); 
    END IF;  
END// 

我读here,使用连接是有效的高效选择。但是我的问题只包含一个表,我觉得我的解决方案(第一个)比第二个更有效,因为连接会比较消耗内存。

如果Employee table足够大,请建议我哪个更好更高效。 哪个更适合我?原因

编辑:我检查了只包含7行的小表,并且两个解决方案都采用相同的时间。

mysql> CALL delete_employee(4); 
Query OK, 1 row affected (0.09 sec) 

我知道SQL函数行为非确定性,因为表启发式。哪个选择更好?要么你有一些想法如何进一步优化查询。

+0

**阅读本** [**问题**](http://stackoverflow.com/问题/ 13487010/how-to-update-same-table-on-deletion-in-mysql) –

回答

0

经过一段时间的思考,我几乎可以肯定它没有什么区别,第一个解决方案可能会稍微慢一点,但在一个不可衡量的方面。

首要的意图是,第一个解决方案更快,因为您首先通过id获取数据,并且只在需要时才更新。

但是MySQL在内部并没有在UPDATE .. JOIN语句中做任何其他的事情,只是在内部,因此也可能更有效。

您的第一个解决方案不会捕获默认情况 - 如果我既没有获得WORKERBOSS,会发生什么情况?

此外,您的执行时间(0.09s)非常高,无法用我所了解的数据库解释到目前为止。

您是否设置了任何索引?

编辑:

table structure you've posted here 后,我有一定的提升提供了结构本身。

1.使用类型int当您存储integer values。数据库可以处理更高效的整数方式

2.为什么自己生成SSN?在PRIMARY KEY使用auto_increment要简单得多处理,当你你使用查找名称添加新员工

ALTER TABLE `Employee` 
    CHANGE `SSN` `SSN` int(11) NOT NULL AUTO_INCREMENT , 
    CHANGE `MSSN` `MSSN` int(11) DEFAULT NULL, 
    ADD KEY `KEY_Employee_MSSN` (`MSSN`); 

3.为您节省了大量的工作?如果是这样,它需要

ALTER TABLE `Employee` 
    ADD UNIQUE KEY `UNI_KEY_Employee` (`name`); 

4.你有指定的固定范围内独一无二的呢?枚举迫使输入是定义的值

ALTER TABLE `Employee` 
    CHANGE `designation` `designation` ENUM('BOSS', 'WORKER') NOT NULL DEFAULT 'WORKER', 
    ADD KEY `KEY_Employee_designation` (`designation`); 

最终结构的一个

mysql> EXPLAIN `Employee`; 

+-------------+-----------------------+------+-----+---------+----------------+ 
| Field  | Type     | Null | Key | Default | Extra   | 
+-------------+-----------------------+------+-----+---------+----------------+ 
| SSN   | int(11)    | NO | PRI | NULL | auto_increment | 
| name  | varchar(64)   | YES | UNI | NULL |    | 
| designation | enum('BOSS','WORKER') | NO | MUL | WORKER |    | 
| MSSN  | int(11)    | YES | MUL | NULL |    | 
+-------------+-----------------------+------+-----+---------+----------------+ 
4 rows in set (0.00 sec) 
+0

This [** Database **](http://stackoverflow.com/questions/13487010/how-to-update-同一表上的删除在MySQL)只包含七个元组! –