[英]Mysql: Select after Insert failing to find rows just inserted
我沒有在程序中使用事務,因此我認為所有數據庫操作都將立即提交。
我有一個php程序,在表中查找值,如果找到,則返回id。 如果找不到,它將寫入新行。 稍后重復,它應該找到我剛剛插入的數據,但是沒有,所以我得到一個重復的錯誤。
我該如何強制mysql寫入數據,以便在插入后返回有效結果? 我試過刷新表,但這並沒有改變我的結果。
更多細節:
我以為這是一個通用的mysql問題,但它似乎與使用Cakephp的模型查詢有關。
我正在使用控制器將CSV文件解析為多個表,因此可以即時綁定模型並使用查詢調用在遇到數據時將數據插入表中。 我在其余的應用程序中都使用CakePHP,但是解析能力是一種一次性功能,因此我沒有花費很多時間來使其優雅。
導入模型沒有關聯的表,因此我手動綁定到跟蹤模型。
將代碼解釋為相關查詢:
$this->Import->bindModel(array('hasOne' => array('Tracking')));
$insert =<<<DONE
INSERT INTO tracking (id, created, employee_id, client_id, borrower_name, loan_number,
loan_amount, activity_id, program_id, rate_id, lock_period,
lo_price, investor_price, committed_price, purchase_advice_price,
lock_type, investor_id, time_taken, notes,audited,audit_notes,
import_notes, import_error, uniqueness)
VALUES (NULL, '%s', %d, %d, '%s', '%s',
%.2f, %d, %d, %d, %d,
%.5f, %.5f, %.5f, %.5f,
%d, %d, %d, '%s', %d, '%s',
'%s', %d, %d)
DONE;
while ($row = fgetscsv($fh))
# Lots of processing deleted
if (! $this->_exists($row))
{
$sql = vsprint($insert, $row);
$this->Import->Tracking->query($sql); # This is where I'll get a duplicate error
}
} # end of function
# I've created a unique index on columns that should be unique and I do the query on
# them here.
private _exists($mydata)
{
$find = "SELECT id FROM tracking WHERE created = '%s' AND employee_id = %d" AND
activity_id = $d AND ...";
$sql = sprintf($find, $mydata[0], $mydata[1]);
return $this->Import->Tracking->query($sql);
}
因此,問題似乎出在Cakephp及其與模型查詢相關的工作上。
我可能可以從Cake中提取此代碼,並使用獨立的php程序,但是由於我已經在使用Cakephp,所以我認為我會將導入模型放到那里。
補充說明:選擇正確,但是由於字跡太長,所以我沒有逐字記錄,我用省略號來表明這一點。 它可以正常工作,因為我可以將其復制/粘貼到mysql會話中並選擇數據。 再次運行它,它將找到數據。
對其他人來說,Cakephp可能會將整個事情包裝成一個大事務,直到退出控制器后才提交該事務嗎? 那不能解釋為什么第二次運行它將找到那些行嗎?
我想我要么需要弄清楚如何使Cakephp提交那些插入,要么我不應該為此使用Model-> query並以另一種方式進行操作,或者不為我的項目的這一部分使用Cakephp。
====
謝謝!
在CakePHP 2.5.5上,僅供將來參考(即使是我自己,如果我忘記了解決方案,以后也找不到自己的答案……您好!),好吧,此問題是由於查詢緩存引起的。 解決方法:
$this->Import->Tracking->query($sql, false);
添加錯誤參數將關閉查詢緩存。 只需閱讀有關方法http://api.cakephp.org/2.5/source-class-Model.html#3363-3366的注釋
您可能正在尋找LAST_INSERT_ID()
http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_last-insert-id
您的$ find不是有效的字符串:
$find = "SELECT id FROM tracking WHERE created = "%s" AND employee_id = %d" AND activity_id = $d AND ...";
// ^ this is terminating the string
您需要將其用單引號引起來,使其成為文字字符串。 像這樣:
$find = 'SELECT id FROM tracking WHERE created = "%s" AND employee_id = %d" AND activity_id = $d AND ...';
或轉義字符串中的引號(盡管不確定在這種情況下為什么要這樣做):
$find = "SELECT id FROM tracking WHERE created = \"%s\" AND employee_id = \"%d\" AND activity_id = $d AND ...";
如果您在表上有一個UNIQUE
約束(並且從代碼中的注釋中可以看到),您可以使用INSERT IGNORE
INSERT IGNORE INTO tracking (...)
VALUES (...)
這就說明了在INSERT
之前執行SELECT
的需要。
要考慮的另一種選擇是將處理CSV文件的方式更改為以下內容:
VARCHAR
類型)和一個auto_incremented id字段 LOAD DATA INFILE
以最有效的方式將CSV文件加載到登台表中 您甚至可以將p3-5包裝到存儲過程中,這可以進一步簡化客戶端代碼。
我認為我遇到的是CakePHP使用Query方法所做的事情。 我對控制器進行了重新編碼,以便它可以動態創建與模型的關聯,並使用內置的模型保存方法。
即使是更多的編碼,它也是一個更優雅的解決方案。 這也使我不必去研究CakePHP的精髓,也不必弄清楚查詢方法在做什么。
感謝大家的想法!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.