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


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

    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)
  • 相关阅读:
    洛谷P1661 扩散
    Vijos1056 图形面积
    Python爬取猪肉价格网并获取Json数据
    C#中巧用Lambda表达式实现对象list进行截取
    Winform中在ZedGraph中最多可以添加多少条曲线
    Nginx配置实例-动静分离实例:搭建静态资源服务器
    解决pip使用异常No module named 'pip'
    C#在循环中使用Random时生成的随机数相同的解决办法
    Winform中自定义ZedGraph右键复制成功后的提示
    C#中巧用Lambda进行数据的筛选查询等处理
  • 原文地址:https://www.cnblogs.com/madao/p/2937830.html
Copyright © 2020-2023  润新知