你的能力得足以应付数据库

程序员还是熟悉一下数据库为好,今天就被坑了一回:

CREATE TABLE `T2` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` char(32) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1000 DEFAULT CHARSET=utf8;

好吧,正常来说,新插入的记录id就应该从1000开始了。然而,在创建完表到正式插入第一条记录之间,你可能发现数据库有需要优化的地方,修改了一下配置,重启mysqld。这个时候,再插入:

mysql> insert into T2(name) values('es');
Query OK, 1 row affected (0.01 sec)

mysql> select * from T2;
+----+------+
| id | name |
+----+------+
|  1 | es   |
+----+------+
1 row in set (0.00 sec)

这算是一件大事吗?是的,太严重了,因为我设了一条规则,根据id来找到这个表属于哪个库,想想mysql建立链接时c api:

MYSQL *mysql_real_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *db, unsigned int port, const char *unix_socket, unsigned long client_flag)

操作每个库使用的是不同的句柄,一个错误的id,别想获得正确的句柄了。

为什么重启之后auto_increment的值就不复存在了呢?简单来说就是auto_increment的值保存在内存,详细看这里:http://biancheng.dnbcw.info/mysql/248738.html

然后嘛就出事了,部分数据丢失,要靠着剩下的部分数据去恢复,这就到了考验mysql能力的时候了。然后突然发现,这方面能力实在不大行,特别碰上情况紧急,更是手忙脚乱。例如拿着一个id列表,对每个id插入几条信息到表中,我不会!我甚至不知道mysql是否有循环这回事,我只想到写个小程序来操作。幸好最后发现这样的操作并不需要,要不就死定了。但是,程序员,你还是熟悉一下数据库吧。循环插入,可以写一个存储过程,或者不关注性能,使用mysql命令写个小脚本也可以,只要你知道mysql命令有一个--execute选项,例如:

mysql test -e "insert into T2(name) values('esw');"

(test为数据库名,如需要用户名或密码,使用-p -u)

存储过程,从来没写过,看这里:http://www.blogjava.net/sxyx2008/archive/2013/02/03/303497.html,自己写一下:

delimiter //
DROP PROCEDURE IF EXISTS loop_insert; 
CREATE PROCEDURE loop_insert( in n INT ) 
BEGIN
DECLARE i INT DEFAULT 0;  
WHILE i < 10  
DO 
INSERT INTO T2(id, name) VALUES(n, 'a'); 
SET i=i+1; 
SET n=n+1;
END WHILE; 
END
//
delimiter ;

delimiter命令用于告诉mysql客户端,遇到'//'的时候才执行输入的指令。使用的时候要先选择T2所在的库,然后

mysql> set @n=20;
Query OK, 0 rows affected (0.00 sec)

mysql> CALL loop_insert(@n);
Query OK, 1 row affected (0.52 sec)

记得要@就行了。 

然后刚才又发现了存储过程中很有用的游标(cursor):http://blog.csdn.net/rdarda/article/details/7881648

也来自己写一下:

delimiter //
DROP PROCEDURE IF EXISTS cursor_test;
CREATE PROCEDURE cursor_test()
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE id_found INT;
DECLARE loop_cursor CURSOR FOR SELECT id FROM T1;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;
OPEN loop_cursor;
FETCH loop_cursor INTO id_found;
REPEAT
INSERT INTO T2(id, name) VALUES(id_found, 'a');
FETCH loop_cursor INTO id_found;
UNTIL done END REPEAT;
CLOSE loop_cursor;
END
//
delimiter ;

T1是之前写的另一个表,这里只需要知道它有一个id字段就可以了。其中的CONTINUE HANDLER在我这边似乎没有用,调用这个存储过程之后依然会有warning。然后FETCH INTO是可以将多个字段赋值到多个变量的,这里没用到而已。

今天还用到的几个命令:

查看创建表的代码:

mysql> show create table T2;
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                          |
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| T2    | CREATE TABLE `T2` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` char(32) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

修改auto_increment:

mysql> alter table T2 auto_increment=100;
Query OK, 2 rows affected (0.05 sec)
Records: 2  Duplicates: 0  Warnings: 0

查看auto_increment和其他状态:

mysql> show create table T2;
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                                             |
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| T2    | CREATE TABLE `T2` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` char(32) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=100 DEFAULT CHARSET=utf8 |
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
原文地址:https://www.cnblogs.com/madao/p/2937830.html