数据误删除,杯具的一天
时间:2010-09-19 来源:cau99
真是杯具啊!
今天不知怎么回事,没经大脑,用root用户就在mysql中执行了delete from tblname1 where id in(select id from tblname2 where ...),结果把tblname1中的数据全删了,幸好有备份,恢复了几个小时要不真就惨了!说句实话mysql的恢复功能确实不咋样。
总之数据操作应该三思而行;DML操作启用事务;做好备份,以免欲哭无泪啊!
本来的目的是删除每个用户下最大id的那条记录,可是mysql不允许根据自身的表来删除数据:
SQL>delete from t where id in (select max(id) from t);
ERROR 1093 (HY000): You can't specify target table 't' for update in FROM clause
模拟过程如下:
SQL>select * from t6;
+------+------+
| id | sal |
+------+------+
| 1 | 500 |
| 2 | 800 |
| 3 | 1000 |
| 4 | 1300 |
| 5 | 2000 |
| 6 | 2200 |
| 7 | 3000 |
| 8 | 3500 |
| 9 | 4000 |
| 10 | 4800 |
+------+------+
SQL>create temporary table t as select max(id) from t6;
Query OK, 1 row affected (0.09 sec)
Records: 1 Duplicates: 0 Warnings: 0
SQL>desc t;
+---------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+---------+------+-----+---------+-------+
| max(id) | int(11) | YES | | NULL | |
+---------+---------+------+-----+---------+-------+
1 row in set (0.00 sec)
SQL>select * from t;
+---------+
| max(id) |
+---------+
| 10 |
+---------+
1 row in set (0.00 sec)
建临时表存放中间结果时没有给max(id)定义别名,杯具开始了
SQL>delete from t6 where id in (select id from t);
Query OK, 10 rows affected (0.00 sec)
SQL>select * from t6;
Empty set (0.00 sec)
竟然都给删除了
SQL>select id from t;
ERROR 1054 (42S22): Unknown column 'id' in 'field list'
单独执行报错,放在in里尽然不报错,晕死!
其实只要给max(id)指定个别名就没问题了,所以CTSA建表时对聚合函数的列一定要指定别名。
使用以下SQL可以从t表中正确select数据:
SQL>select `max(id)` from ttt;
+---------+
| max(id) |
+---------+
| 10 |
+---------+
1 row in set (0.00 sec)
`是esc下面那个
所以以下SQL也可以正确删除数据:
SQL>delete from t6b where id in (select `max(id)` from ttt);
Query OK, 1 row affected (0.00 sec)