这个问题按照我的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使用连接对Efficient SELECT有效。但我的问题只包括一个表,我觉得我的解决方案(第一个)比第二个效率高,因为连接会比较消耗内存。
如果Employee table
足够大,请建议我哪个更好,更有效率。 哪个更适合我?原因
编辑:我检查过只有7行的小表,两个解决方案都需要同时进行。
mysql> CALL delete_employee(4);
Query OK, 1 row affected (0.09 sec)
我知道SQL函数的行为是非确定性的,因为表启发式。哪个选择更好?如果你有一些想法如何进一步优化查询。
答案 0 :(得分:0)
经过一段时间的思考,我几乎可以肯定它没有什么区别,第一个解决方案可能会稍微慢一些,但是在一个不可测量的维度上。
第一个意图是,第一个解决方案更快,因为你首先通过id获取数据,并且仅在nessesary时更新。
但MySQL内部在UPDATE .. JOIN
语句中没有做任何其他事情,只是在内部,因此也可能更有效。
您的第一个解决方案没有发现默认情况 - 如果我既没有WORKER
或BOSS
又会怎样?
此外,您的执行时间(0.09秒)非常高,目前为止无法用我对您的数据库进行解释。
您是否设置了任何索引?
修改强>
查看table structure you've posted here后 我对结构本身有一些改进。
1。在存储int
时使用类型integer values
。数据库可以更有效地处理整数方式
2。为什么要自己生成SSN
?在auto_increment
上使用PRIMARY KEY
可以更轻松地处理并在您添加新员工时为您节省大量工作
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)