2011-08-31 59 views
3

在我的表,我有两个领域:v_idip_address。只有当IP地址不存在时,我才想将一些数据插入此表中。INSERT INTO查询只如果记录不存在

Google'ing后,我遇到了INSERT IGNORE INTO声明,这是我的代码:

public function update_visits($ip_address) 
{ 
    $sql = 'INSERT IGNORE INTO `24h_visits` (ip_address) VALUES (?)'; 
    if($this->db->query($sql, array($ip_address))) 
    { 
     return TRUE; 
    } 
    return FALSE; 
} 

它运行正常,没有错误,但重复的行仍在做,即使同一IP传递作为参数。

任何人都得到了线索?谢谢。

+0

是ip_address表上的主键? –

+0

也许你可以使用'WHERE NOT EXISTS' – ocodo

回答

5

UNIQUE约束添加到您的ip_address列。

然后,如果您的查询尝试添加重复的ip_address行(除非您使用INSERT IGNORE),则会失败。

+0

+1为是第一:) –

6

你必须为INSERT IGNORE创建ip_address一个UNIQUE指数工作:

ALTER TABLE 24h_visits 
    ADD UNIQUE INDEX(ip_address) 

然而,我还没有看到你的架构的全部,但我认为有一个列存储上次访问的时间戳。这是唯一有意义的方法(所以你可以每隔24小时清除访问次数)。

在这种情况下,你其实不想INSERT IGNORE,但INSERT ... ON DUPLICATE KEY UPDATE代替。假设你有一栏叫last_visit

INSERT INTO 24h_visits (ip_address, last_visit) 
    VALUES ('$ip_address', NOW()) 
    ON DUPLICATE KEY UPDATE last_visit = NOW(); 

随着INSERT IGNORE,新行是永远不会插入,这样的话你总是有第一个值永远插在last_visit,这(我看到它的方式)不完全正确。

+1

+1'UNIQUE'约束是最好的方式。您可以在数据库中加强完整性。 – alex

+0

@alex:你今天是如此DBAish :-) – zerkms

+1

@zerkms不同的日子,不同的帽子:d – alex

3

其他的答案实际上不回答这个问题:创建唯一索引防止被插入,这是一个好主意重复的,但它并没有回答“如何插入如果不是已经在那里。”
这是你如何做到这一点:

INSERT IGNORE INTO 24h_visits (ip_address) 
select ? 
where not exists (select * from 24h_visits where ip_address = ?) 

此外,这种方法不需要对架构进行任何更改。

+2

我试图回答与不是有人问这个问题,但我相信OP实际上想要。 – NullUserException

+0

我只是对你的初始答案进行了大胆的处理*放一个独特的索引,我认为这是一个糟糕的主意 - 那么在正常处理过程中你必须处理异常。当然把这个指数,但你不想*避免*例外 – Bohemian