【问题标题】:check MySQL if row is not exist, then insert (Without unique key)如果行不存在,则检查 MySQL,然后插入(没有唯一键)
【发布时间】:2017-09-05 17:03:11
【问题描述】:

我们有 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

现在我们需要一个查询来检查“命中”表中是否不存在具有特定 PostID 和 IP 地址的行,插入新行并增加帖子。命中一个单位(这是一个计数器)。

我们测试了这个查询:

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

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

【问题讨论】:

    标签: mysql insert insert-update not-exists


    【解决方案1】:

    要像@gordon-linoff 所说的那样,每个帖子都有唯一的 ip:

    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 时更新 hits 列:

    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;
    

    【讨论】:

    • 挑战在于: 1- 当用户打开一个帖子页面时,增加该帖子的点击率。 2-如果该用户打开另一个帖子,其点击量会增加。 3- 如果该用户第二次打开帖子,不要这样做!
    • 然后像@gordon-linoff 所说的那样为点击创建一个唯一索引。
    • 用插入示例更新了我的答案。
    • 我的问题是:我们希望如果发生重复,什么都不做,也不会显示错误!但如果它是新行,请插入它,然后更新另一个表列。只要回答这个!!
    • 您使用了 gordon 已经说过的触发器。有关详细信息,请参阅我的更新回复。
    【解决方案2】:

    您只需要在 两个 列而不是一个列上具有唯一索引/约束:

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

    那么你可以使用on duplicate key update

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

    【讨论】:

    • 不!我们希望如果出现重复,什么也不做!但如果是新行,则插入它,然后更新另一个表列。
    猜你喜欢
    • 1970-01-01
    • 2010-12-30
    • 2010-12-05
    • 2017-09-19
    • 1970-01-01
    • 2016-01-06
    • 1970-01-01
    • 1970-01-01
    • 2017-04-24
    相关资源
    最近更新 更多