2012-11-22 50 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)只包含七個元組! –