检查 MySQL 如果行不存在,则插入(没有唯一键)
check MySQL if row is not exist, then insert (Without unique key)
我们有 2 个这样的 table:
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' table 中是否不存在具有特定 PostID 和 IP 地址的行,插入一个新行并增加 posts.Hits 个单位(这是一个计数器)。
我们测试了这个查询:
INSERT INTO table (field) VALUES (value) ON DUPLICATE KEY UPDATE field=value
但是如您所见,IP 和 PostID 不能是唯一键。他们可以为不同的用户复制。
如果没有PostID+IP,有没有办法在一次查询中插入和更新?
您只需要在 两个 列而不是一个列上有唯一的 index/constraint:
create unique index unq_hits_postid_ip on hits(postid, ip);
那你可以用on duplicate key update
.
但是,这将适用于 one table。在 another table 中递增计数器是一个奇怪的设计。为什么不在 hits
中设置计数器?如果您必须增加另一个 table,那么您将需要一个触发器。
要让每个 post 拥有唯一的 ip,你就像@gordon-linoff 说的那样:
create unique index unq_hits_postid_ip on hits(postid, ip);
然后你可以使用下面的语法来"ignore"插入:
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 ;
虽然我自己不会这样设计,但我根本不会跟踪 table 中的点击数!获取点击次数是您可以在运行时使用 SQL.
轻松完成的事情
要计算特定 post 的点击次数(您需要此处 posts.title 的索引):
select
count(1) as hits
from posts p
join hits h on p.id = h.postid
where p.title = 'Title 2';
要获得多个 post 的点击率,您可以使用 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;
我们有 2 个这样的 table:
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' table 中是否不存在具有特定 PostID 和 IP 地址的行,插入一个新行并增加 posts.Hits 个单位(这是一个计数器)。
我们测试了这个查询:
INSERT INTO table (field) VALUES (value) ON DUPLICATE KEY UPDATE field=value
但是如您所见,IP 和 PostID 不能是唯一键。他们可以为不同的用户复制。 如果没有PostID+IP,有没有办法在一次查询中插入和更新?
您只需要在 两个 列而不是一个列上有唯一的 index/constraint:
create unique index unq_hits_postid_ip on hits(postid, ip);
那你可以用on duplicate key update
.
但是,这将适用于 one table。在 another table 中递增计数器是一个奇怪的设计。为什么不在 hits
中设置计数器?如果您必须增加另一个 table,那么您将需要一个触发器。
要让每个 post 拥有唯一的 ip,你就像@gordon-linoff 说的那样:
create unique index unq_hits_postid_ip on hits(postid, ip);
然后你可以使用下面的语法来"ignore"插入:
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 ;
虽然我自己不会这样设计,但我根本不会跟踪 table 中的点击数!获取点击次数是您可以在运行时使用 SQL.
轻松完成的事情要计算特定 post 的点击次数(您需要此处 posts.title 的索引):
select
count(1) as hits
from posts p
join hits h on p.id = h.postid
where p.title = 'Title 2';
要获得多个 post 的点击率,您可以使用 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;