【问题标题】:How to Update same table on deletion in MYSQL?如何在 MYSQL 中删除时更新同一张表?
【发布时间】:2012-11-09 08:02:39
【问题描述】:

在我的数据库中,我有一个表 Employee 具有递归关联(员工可以是其他员工的老板):

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 here 那个this trigger is not possible 因为In MySQL triggers can't manipulate the table they are assigned to

是否有一些其他可能的方法来做到这一点?是否可以使用Nested Query?有人可以建议我其他方法吗?一个建议就足够了,但应该是有效的。

编辑
我得到了答案: 而不是触发stored proceduretwo consecutive queries 是可能的。 Firstsecond

我为这个问题写的解决方案如下,工作得很好!

  • 我正在为MYSQL version older then 5.5 编写的辅助信号函数。

分隔符 //

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//

分隔符;

【问题讨论】:

  • 您可以尝试以下方法吗?对于您的要求,它看起来太简单了,特别是在动态删除方面...update Employeeset MSSN=(select mssn from employeewhere ssn = '4');delete from employee where ssn = 4;
  • @bonCodigo:你的意思是两个连续的删除查询。可以考虑...但是我必须考虑一下-谢谢!
  • 是的,两个连续查询。似乎 sql server 中的 EntityFramework 提供了存储库模式 - 它可以允许您通过存储过程使存储库的删除函数递归。我个人没有做过。也许你可以在这里模仿。有趣的问题 +1
  • Please add a comment if some one vote-downs
  • 另见:BOTH SOLUTIONS

标签: mysql sql triggers mysql-error-1442


【解决方案1】:

使用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

使用存储过程,您可以简单地删除所需的行,然后更新同一个表。这应该可以防止错误消息。

【讨论】:

  • 你的意思是我应该调用删除和更新两者的过程而不是触发器...我会尝试。-谢谢
  • 是的,您可以在存储过程中运行任意数量的语句。您可以在单个存储过程中对任何表执行任何 CRUD 语句。如果答案确实有帮助,请点赞。谢谢。
  • @OMGPonies:谢谢! ...在您的个人资料中添加一些联系人..我正在尝试与您联系。
  • @这是你的错:也谢谢你!
  • @OMGPonies 嗨,您好,看来您已经下线了。我需要您帮助解决这个问题:MySQL trigger On Insert/Update events 我试图回答,我想它应该可以工作,但它不起作用。你能在那里添加一个答案吗?
【解决方案2】:

不要进行硬删除,而是进行软删除。如果要删除该行,请添加 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} 更新同一个表。请检查这个

【讨论】:

  • 这是一个建议,不是答案。
猜你喜欢
  • 1970-01-01
  • 2021-02-08
  • 1970-01-01
  • 2016-12-06
相关资源
最近更新 更多