一天工友碰到問題,插入新數據的時候老是會寫入兩條。他一直懷疑是本身代碼有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技術博客必定頗有趣。