一天工友碰到问题,插入新数据的时候老是会写入两条。他一直怀疑是本身代码有BUG、又或是数据库设置错误,百思不得其解,而后就和我说了这个奇怪现象,我俩就一块儿走近科学。php
一段简单的SQL语句背后究竟隐藏着什么惊天秘密!html
$this->db->query("INSERT INTO `student` (`name`, `selected`, `score`, `class`) VALUES ('小明', 1, 100, 1)");
这个SQL语句很是简单,不可能有错误。sql
MYSQL表也检查了,在数据库客户端中此语句完美运行,只插入了一条新数据。因而我怀疑是否是CI的query方法有问题。CI的query方法是由不一样数据库驱动控制的,工友用的是PDO,因此打开 ./system/database/drivers/pdo/pdo_driver.php,查看_execute这个实现query的方法。数据库
CI的PDO驱动中负责query的方法fetch
function _execute($sql) { $sql = $this->_prep_query($sql); $result_id = $this->conn_id->prepare($sql); $result_id->execute(); if (is_object($result_id)) { if (is_numeric(stripos($sql, 'SELECT'))) { $this->affect_rows = count($result_id->fetchAll()); $result_id->execute(); } else { $this->affect_rows = $result_id->rowCount(); } } else { $this->affect_rows = 0; } return $result_id; }
一看代码,我和个人工友都惊呆了。this
if (is_numeric(stripos($sql, 'SELECT'))) { $this->affect_rows = count($result_id->fetchAll()); $result_id->execute(); }
你这么写数据库驱动你家里人知道吗?spa
即便说下面那个execute多是出现了GOTO FAIL那种代码合并的BUG(详情传送门:http://www.2cto.com/os/201402/281454.html),那上面那句count又是什么回事!你写PDO驱动的时候觉得PDO是产品设计草图的意思吧?设计
若是有人一时没有反应过来这个BUG的精髓,我稍微讲一下:此代码会搜索最后执行的SQL语句,只要发现含有字符串“select”(仍是不区分大小写的哦),就会第二次执行这条SQL。code
工友的表设计中有一个selected字段,因此每次添加都会有两条……htm
这么酷炫的BUG拿来写MYSQL技术博客必定颇有趣。