如果行不存在则检查MySQL,然后插入(没有唯一键)

时间:2017-04-10 15:08:16

标签: mysql insert insert-update not-exists

我们有2个这样的表:

1:帖子

ID    Title    Hits
1    Title 1    4
2    Title 2    7
3    Title 3    19
4    Title 4    8

2:点击

ID    PostID     IP
1       2     5.9.9.45
2       3     5.9.9.45
3       2     72.5.4.9
4       4     5.9.9.45

现在我们需要一个查询来检查'hits'表中是否存在具有特定PostID和IP地址的行,插入新行并增加posts.Hits一个单位(它是一个计数器)。

我们测试了这个查询:

INSERT INTO table (field) VALUES (value) ON DUPLICATE KEY UPDATE field=value

但是如您所见,IP和PostID不能是唯一键。它们可以复制给不同的用户。 如果没有PostID + IP,有没有办法在一个查询中插入和更新?

2 个答案:

答案 0 :(得分:0)

您只需要在两个列而不是一个

列上使用唯一索引/约束
create unique index unq_hits_postid_ip on hits(postid, ip);

然后您可以使用on duplicate key update

但是,这将适用于一个表。增加另一个表中的计数器是一个奇怪的设计。为什么不在hits中设置计数器?如果你必须在另一个表中增加,那么你需要一个触发器。

答案 1 :(得分:0)

要为每个帖子设置唯一的ip,你会喜欢@ gordon-linoff说:

create unique index unq_hits_postid_ip on hits(postid, ip);

然后您可以使用以下语法“忽略”插入:

insert into hits (postid, ip) values (2,'5.9.9.45') on duplicate key update id=id;

然后,您可以使用触发器确保在插入IP时更新命中列:

DELIMITER /

CREATE TRIGGER trg_ai_hits AFTER INSERT ON hits
  FOR EACH ROW
BEGIN
  UPDATE posts SET hits = hits + 1 WHERE id = NEW.postid;
END;
/

DELIMITER ;

虽然我不会自己设计这种方式,但我根本不会记录表格中的点击次数!获取命中数是您可以在运行时使用SQL轻松完成的任务。

要计算特定帖子的点击次数(你想要posts.title的索引):

select 
count(1) as hits 
from posts p 
join hits h on p.id = h.postid
where p.title = 'Title 2';

要获得多个帖子的点击,您可以使用GROUP BY子句:

select 
p.title, 
count(1) as hits 
from posts p 
join hits h on p.id = h.postid
where p.title in ('Title 2', 'Title 3')
group by p.title
order by hits desc;

另外,我认为多次存储相同的IP是件好事。根据您当前的设计,您可以检查IP号访问您网站的次数:

select 
ip, 
count(postid) access_number 
from hits 
group by ip
order by access_number desc;