今天简单说说MySQL的主键和***索引约束:PRIMARYKEYandUNIQUEIndexConstraints文章不长,保证有收获。触发约束检测的时机:当insertupdate检测到约束违反时,不同存储引擎的处理动作不同。如果存储引擎支持事务,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***rowid=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,2rowsaffectedisinteresting?画外音:本文所有实验均基于MySQL5.6。总结:对于主键和***索引约束:在执行insert和update时,会触发约束检查。当InnoDB违反约束时,它会回滚相应的SQL。当MyISAM违反约束时,相应的SQL将被中断,这可能会导致意外的结果集。您可以使用insert...onduplicatekey来指定触发约束时的操作。通常使用显示警告;查看和调试违反约束的大数据量、高并发的ERROR互联网业务。为了大家的身心健康,请使用InnoDB。【本文为专栏作者《58神剑》原创稿件,转载请联系原作者】点此阅读更多该作者好文
