2012-11-21 45 views
12

在我的數據庫中,我有一個具有遞歸關聯的表Employee(員工可以是其他員工的老闆):如何在MYSQL中刪除相同的表?

create table if not exists `employee` (

    `SSN` varchar(64) not null, 
    `name` varchar(64) default null, 
    `designation` varchar(128) not null, 
    `MSSN` varchar(64) default null, 
    primary key (`ssn`), 
    constraint `fk_manager_employee` foreign key (`mssn`) references employee(ssn) 

) engine=innodb default charset=latin1; 

mysql> describe Employee; 
+-------------+--------------+------+-----+---------+-------+ 
| Field  | Type   | Null | Key | Default | Extra | 
+-------------+--------------+------+-----+---------+-------+ 
| SSN   | varchar(64) | NO | PRI | NULL |  | 
| name  | varchar(64) | YES |  | NULL |  | 
| designation | varchar(128) | NO |  | NULL |  | 
| MSSN  | varchar(64) | YES | MUL | NULL |  | 
+-------------+--------------+------+-----+---------+-------+ 
4 rows in set (0.00 sec) 

然後插入:

mysql> insert into Employee values 
    -> ("1", "A", "OWNER", NULL), 
    -> ("2", "B", "BOSS", "1"), 
    -> ("3", "C", "WORKER", "2"), 
    -> ("4", "D", "BOSS", "2"), 
    -> ("5", "E", "WORKER", "4"), 
    -> ("6", "F", "WORKER", "1"), 
    -> ("7", "G", "WORKER", "4") 
    -> ; 
Query OK, 7 rows affected (0.02 sec) 
Records: 7 Duplicates: 0 Warnings: 0 

現在我在表格中的行之間有以下等級關係(所有者>老闆>工人):

 A 
    /\ 
    B F 
/\ 
c D 
    /\ 
    G E 

以下是select語句表:

mysql> SELECT * FROM Employee; 
+-----+------+-------------+------+ 
| SSN | name | designation | MSSN | 
+-----+------+-------------+------+ 
| 1 | A | OWNER  | NULL | 
| 2 | B | BOSS  | 1 | 
| 3 | C | WORKER  | 2 | 
| 4 | D | BOSS  | 2 | 
| 5 | E | WORKER  | 4 | 
| 6 | F | WORKER  | 1 | 
| 7 | G | WORKER  | 4 | 
+-----+------+-------------+------+ 
7 rows in set (0.00 sec) 

現在,我想強加約束,如:If any employee (BOSS) deleted then new BOSS of workers under him become immediate BOSS of deleted employee (Old BOSS)。例如如果我刪除D,則B成爲GE的BOSS。

爲此,我也寫了觸發如下:

mysql> DELIMITER $$ 
mysql>  CREATE 
    ->  TRIGGER `Employee_before_delete` BEFORE DELETE 
    ->   ON `Employee` 
    ->   FOR EACH ROW BEGIN 
    ->   UPDATE Employee 
    ->   SET MSSN=old.MSSN 
    ->   WHERE MSSN=old.MSSN; 
    ->  END$$ 
Query OK, 0 rows affected (0.07 sec) 

mysql>  DELIMITER ; 

但是當我執行一些缺失:

mysql> DELETE FROM Employee WHERE SSN='4'; 
ERROR 1442 (HY000): Can't update table 'Employee' in stored function/trigger 
because it is already used by statement which invoked this stored 
function/trigger. 

learn herethis trigger is not possible因爲In MySQL triggers can't manipulate the table they are assigned to

有沒有一些其他可能的方式來做到這一點?它可能使用Nested Query?有人能告訴我其他方法嗎?一個建議就足夠了,但應該是有效的。

編輯
我得到了答案: INSTEAD OF觸發器的stored proceduretwo consecutive queries是可能的。 Firstsecond

我爲此問題編寫的解決方案如下,運行良好!

  • A作爲我寫MYSQL version older then 5.5一個輔助信號功能。

DELIMITER //

CREATE PROCEDURE `my_signal`(in_errortext VARCHAR(255)) 
BEGIN 
    SET @sql=CONCAT('UPDATE `', in_errortext, '` SET x=1'); 
    PREPARE my_signal_stmt FROM @sql; 
    EXECUTE my_signal_stmt; 
    DEALLOCATE PREPARE my_signal_stmt; 
END// 
  • 存儲過程以從Employee表刪除的僱員。
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// 

DELIMITER;

+1

你可以嘗試以下嗎?它看起來對你的要求未免過於簡單特意在具有動態刪除的條款...... '更新Employee' '設置MSSN =(選擇從employee' '其中SSN =「4」 mssn);' 從僱員處刪除ssn = 4;' – bonCodigo

+0

@bonCodigo:你的意思是連續刪除兩個查詢。可以考慮......但我必須考慮這個 - 謝謝! –

+1

是兩個連續的疑問。看起來,sql server中的EntityFramework提供了Repository Pattern - 它可以讓你通過存儲過程使存儲庫的刪除函數遞歸。我本人沒有親自做過。也許你可以在這裏模仿相同的東西。有趣的問題+1 – bonCodigo

回答

4

使用stored procedure

UPDATE b 
    SET b.mssn = a.mssn 
    FROM EMPLOYEE a 
    JOIN EMPLOYEE b ON b.mssn = a.ssn 
WHERE a.ssn = @deletedBoss 

DELETE FROM employee WHERE ssn = @deletedBoss 

與存儲過程,你可以簡單地刪除你想要的行,之後,更新同一個表。這應該防止錯誤消息。

+0

你的意思是代替觸發器,我應該調用Procedure刪除和更新兩個...我會試試.-謝謝 –

+0

是的,你可以在存儲過程中運行儘可能多的語句。您可以在單個存儲過程中的任何表上執行任何CRUD語句。如果答案確實有幫助,請加倍努力。謝謝。 –

+1

@GrijeshChauhan:我只是添加了代碼,而不是發佈自己的代碼。 –

0

而不是做一個硬刪除,做一個軟刪除。如果要刪除行,請添加is_deleted列並將其設置爲1。在表上創建after_update觸發器。

DELIMITER $$ 
    CREATE 
    TRIGGER `Employee_after_update` AFTER UPDATE 
     ON `Employee` 
     FOR EACH ROW BEGIN 
     UPDATE Employee 
     ............... 
     WHERE NEW.is_deleted=1; 
     DELETE FROM Employee WHERE NEW.is_deleted=1 
    END$$ 

我不確定您是否可以爲after_ {insert,delete,update}更新同一張表。請檢查這個

+0

我們無法更新觸發器上的表格被調用! –

+0

這是一個建議,而不是答案。 – Pacerier

相關問題