2009-07-27 117 views
3

我有一个名为user_ips的表来跟踪用户,以防他们删除他们的cookie或更改浏览器。无论如何,下面的代码很简单。它更新user_ips中与用户ID和IP相同的条目。如果查询没有更新任何行,那么这意味着该用户的IP不在表中,因此它会插入它。奇怪的行为与PHP中的mysql_affected_rows()

$site->query('UPDATE `user_ips` SET `last_time` = UNIX_TIMESTAMP(), `user_agent` = \''.$this->user_agent.'\' WHERE `ip` = '.$this->ip.' AND `userid` = '.$this->id); 
if(mysql_affected_rows() == 0) 
{ 
    $site->query('INSERT INTO `user_ips` SET `userid` = '.$this->id.', `ip` = '.$this->ip.', `first_time` = UNIX_TIMESTAMP(), `last_time` = UNIX_TIMESTAMP(), `user_agent` = \''.$this->user_agent.'\''); 
} 

问题是mysql_affected_rows()有时会返回0,即使用户当前的ID和IP存在一行。那么代码会向表中添加相同IP的另一行。

如果你想知道,$ site是我为我的网站做的mysql类,它执行的唯一查询是通过query()传递给它的唯一查询,没有其他,因此这不是类问题。哦,IP被存储为长IP,所以它不需要引号。

回答

7

我直接在这里引用的PHP文件:

当使用UPDATE查询,MySQL不会更新,其中新价值是一样的旧值列。这会造成mysql_affected_rows()实际上可能不等于匹配的行数的可能性,而只是实际上受查询字面影响的行数。

所以在你的情况下,当UNIX_TIMESTAMP()返回相同的值(例如,来自同一客户端的两个请求在同一秒内)时,mysql_affected_rows()将返回0。

+0

这很有道理谢谢。 – fent 2009-07-27 14:00:10

1

要建立在slipbull的答案上​​,处理这个问题的最简单方法可能是简单地执行一个SELECT查询来评估是否需要INSERT。另一个解决方案是在创建用户时简单地插入记录,因为这将保证有效的记录。

+0

我以前正在做另一个SELECT COUNT(*)查询来检查,但我将其更改为保存一个查询。但我想我应该回去。 – fent 2009-07-27 14:01:11

1

你可以设置你的主键跨度userid和ip。这样可以确保您没有重复条目,但是如果您不打算添加select来检查记录存在,则必须在插入查询中禁止出现错误。

+0

我不认为这是可能的在MySQL中。用户可以有很多IP,一个IP可能属于多个用户。因此,用户ID和IP的组合必须是唯一的。 – fent 2009-07-27 14:05:43