当前位置: 首页 > 科技观察

我的CA,为什么一条SQL语句只执行了一半?

时间:2023-03-16 10:21:37 科技观察

今天简单说说MySQL的主键和唯一索引约束:PRIMARYKEY和UNIQUEIndexConstraints,了解奇怪的异常。触发约束检测的时机:insert;更新;当检测到违反约束时,不同存储引擎的处理动作是不同的。如果存储引擎支持事务,SQL会自动回滚。例子:createtablet1(idint(10)primarykey)engine=innodb;insertintot1values(1);insertintot1values(1);由于违反约束,第二次插入将导致回滚。通常你可以使用:showwarnings;在违反约束后查看错误消息。如果存储引擎不支持事务,SQL的执行就会中断。这时候,后面符合条件的行可能不会被操作,导致意想不到的结果。示例:createtablet2(idint(10)unique)engine=MyISAM;insertintot2values(1);insertintot2values(5);insertintot2values(6);insertintot2values(10);updatet2setidid=id+1;update执行后,猜猜你会得到Set什么结果?猜一:2,6,7,11猜二:1,5,6,10。..没有一个是正确的。正确答案是:2,5,6,10第一行id=1,加1后,不违反唯一约束,执行成功;第二行id=5,加1后,因为存在id=6的记录,违反了unique约束,SQL终止,修改失败;第三行id=6,第四行id=10的将不再执行;画外音:这也太操蛋了,一条update语句,一部分执行成功,一部分执行失败。为了避免这种情况,请使用InnoDB存储引擎。当InnoDB遇到约束违背时,会自动回滚update语句,不会有行被修改成功。画外音:大家把存储引擎换成InnoDB,再跑一遍上面的例子,印象更深了。另外,对于insert的约束冲突,可以使用:insert...onduplicatekey来指出违反主键或唯一索引约束时需要执行的额外操作。例子:createtablet3(idint(10)unique,flagchar(10)default'true')engine=MyISAM;insertintot3(id)values(1);insertintot3(id)values(5);insertintot3(id)values(6);insertintot3(id)值(10);insertintot3(id)值(10)onduplicatekeyupdateflag='false';插入执行后,猜猜会发生什么?插入id=10的记录会违反唯一约束,此时执行updateflag='false',所以更新了一行记录。这相当于执行:updatet3setflag='false'whereid=10;仔细看,返回insert的结果,提示:QueryOK,2rowsaffected有意思吗?画外音:本文所有实验均基于MySQL5.6。总结一下主键和唯一索引约束:当执行insert和update时,会触发约束检查;当InnoDB违反约束时,会回滚相应的SQL;当MyISAM违反约束时,会中断相应的SQL,这可能会导致意外的结果集;您可以使用insert...onduplicatekey来指定触发约束时的操作;通常使用显示警告;查看和调试违反约束的ERROR;对于互联网的大数据量和高并发业务,为了大家的身心健康,请使用InnoDB。【本文为专栏作者《58神剑》原创稿件,转载请联系原作者】点此阅读更多该作者好文