活动记录WHERE子句中的额外合取:它们来自哪里?

时间:2014-10-30 18:46:05

标签: php mysql codeigniter activerecord

当我正在使用的CodeIgniter应用程序尝试特定的UPDATE操作时,我收到一个非常奇怪的数据库错误。

Active Record呼叫是:

$this->db->update('eval_events',
                  array('eval_event_totalscore'=>$result['average_score'],
                        'eval_event_average_totalscore=>$result['average_score']),
                  array('eval_event_id'=>$eval_event_id));

报告的错误是:

Error Number: 1054

Unknown column 'id' in 'where clause'

UPDATE `eval_events` SET `eval_event_totalscore` = '40.0000', `eval_event_average_totalscore`
= '40.0000' WHERE `id` = '581' AND `id` = '581' AND `id` = '581' AND `id` = '581' AND `id` = 
'581' AND `id` = '581' AND `id` = '581' AND `id` = '581' AND `id` = '581' AND `id` = '581' AND 
`id` = '581' AND `id` = '581' AND `id` = '581' AND `id` = '581' AND `id` = '581' AND `id` = '581'
AND `eval_event_id` = '565'

咦?什么是那些涉及来自“id”的额外合取?

显然我没有通过它们,我对CI_active_record.php的解读没有给我任何线索。

可能相关的另外三条信息:

  1. 据我所知,这种失败只发生在我的开发机器上。查询似乎在生产机器上很好。
  2. 如果我将此来电发表评论update(),那么跟随<{em>}对update()的调用就会以完全相同的方式被破坏。
  3. 值'581'在这些更新所属的操作的整体上下文中是重要的,但它是不同表中的键(并且无论如何,它绑定到名为`pid`的列,而不是`id`)。
  4. 感觉就像Active Record代码已经缓存了`id` ='581',并且有一些东西导致它在此时将该缓存的内容咳嗽到我的UPDATE语句中。

    我承认我不明白Active Record的start_cache() / stop_cache() / flush_cache()方法究竟应该有什么好处 - 但它应该无关紧要,因为grep -r告诉我在应用程序的代码库中没有任何地方调用start_cache()

    只是为了笑容,我尝试在失败的$this->db->flush_cache()电话之前立即拨打update(),但它没有改变任何内容。

    我不知道下一步该往哪里试图解决这个问题。

    有什么想法吗?任何人吗?

1 个答案:

答案 0 :(得分:0)

好的:echovar_export()debug_print_backtrace()来救援。

事实证明,在执行失败update()调用的函数之前,有一个函数总共被调用了16次。 16恰好是坏UPDATE语句中额外的`id` ='581'合取的数量。

之前的功能是以下代码(我没有编写任何这个垃圾,BTW):

$this->db->where('id',$pid);  // <=== WTF???
$sql = "SELECT id FROM project_score WHERE pid=$pid AND uid=$uid AND scoretype=1";
$result = $this->db->query($sql)->row_array();

这张照片出了什么问题?

嗯,除了在所有中使用Active Record 的可疑选择之外,* Active Record query()方法不使用先前调用{{1}的任何东西。 }}。

因此,16个虚假条件的队列仍然悬而未决,等待将自己附加到第一个毫无疑问的where()(或update()或其他)来电。

为什么生产系统上也不会发生这种情况?

好吧,在我的开发系统上,我暂时注释掉了一些 else (我并不真正关心)因为我本地PHP中缺少配置而失败的东西 - 我没有那时候感觉就像重建一样。

显然,无论我评论出来的是什么,其中包含一个Active Record调用,其中有16个条件的队列被强制执行 - 但它们恰好对那个特定的调用是良性的。

啧!

*所以他的想法是这个“活跃记录”的讽刺,无论如何?

如何让select()之类的函数在全局对象上排队?这是一个好主意?难道没有更好的设计使每个SQL语句成为一个不同的对象,因此在构造一个SQL语句时所犯的错误不会在应用程序的完全不同的部分中破坏另一个错误吗?