Mysql:在Insert无法找到刚插入的行后选择

时间:2013-07-26 21:39:25

标签: php mysql cakephp-2.3

我没有在我的程序中使用事务,所以我认为所有数据库操作都会立即提交。

我有一个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-&gt;查询并以另一种方式执行,或者不要将Cakephp用于我的项目的这一部分

====

谢谢!

5 个答案:

答案 0 :(得分:1)

在CakePHP 2.5.5上,仅供将来参考(即使是我自己,如果我忘记解决方案并在将来找到我自己的答案......嗨自己!),好吧,这个问题是由于查询缓存造成的。修复:

$this->Import->Tracking->query($sql, false);

添加 false 参数将关闭查询缓存。只需阅读方法http://api.cakephp.org/2.5/source-class-Model.html#3363-3366

的评论

答案 1 :(得分:0)

答案 2 :(得分:0)

您的$ 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 ...";

答案 3 :(得分:0)

如果您的表格有UNIQUE约束(并且您的代码中的评论我看到您这样做),您可以使用INSERT IGNORE

INSERT IGNORE INTO tracking (...)
VALUES (...)

这表明在SELECT之前执行INSERT的必要性。


要考虑的另一个选择是将CSV文件的处理方式更改为以下内容:

  1. 创建一个没有约束的临时表,其中包含用于导入数据的所有必需列(最好是VARCHAR类型)和auto_incremented id字段
  2. 使用LOAD DATA INFILE以最有效的方式将CSV文件加载到临时表中
  3. 现在您可以使用所有SQL工具轻松清理,规范化,转换,验证参与表和事实表,并在临时表中显示数据
  4. 将数据从不稳定的表格插入事实表格
  5. 截断您的临时表
  6. 您甚至可以将p3-5包装到存储过程中,这可以进一步简化客户端代码。

答案 4 :(得分:0)

我认为我遇到的是CakePHP对Query方法所做的事情。我重新编码控制器,以便动态创建与模型的关联,并使用内置的模型保存方法。

这是一个更优雅的解决方案,即使它是更多的编码。它还使我不必深入研究CakePHP的内容,并弄清楚查询方法在做什么。

感谢大家的想法!