为什么多次执行查询后,我收到一条成功消息,提示“已插入2行”?

时间:2018-07-15 12:07:26

标签: php mysql sql mysqli pdo

我有2个具有一对一关系的表:

               post_views table
    ___________________________________
   |        |             |           |
   |   id   |   post_id   |   views   |
   |________|_____________|___________|




                   posts table
    __________________________________________
   |        |           |          |         |
   |   id   |   title   |   text   |    ..   |
   |________|___________|__________|_________|
post_id表中的

post_viewsid表中的posts连接起来。

两个表中的id是主变量,并且自动递增,而post_id是唯一的。

这是post_views的索引的屏幕截图: https://prnt.sc/k6no10

每个帖子在post_views表中应该只有一行。

我运行此查询以插入新行或增加视图,如果存在post_id

INSERT INTO post_views (`post_id`, `views`) VALUES (1, 1) ON DUPLICATE KEY UPDATE `views` = `views`+1

已成功执行,并插入了新行:

 ____________________________________
|          |             |           |
|    id    |   post_id   |   views   |
|__________|_____________|___________|
|          |             |           |
|    1     |     1       |    1      |
|          |             |           |
|__________|_____________|___________|

然后,当我再次运行相同的查询以增加视图时,我收到一条成功消息,提示2 rows inserted,行现在是:

____________________________________
|          |             |           |
|    id    |   post_id   |   views   |
|__________|_____________|___________|
|          |             |           |
|    1     |     1       |    2      |
|          |             |           |
|__________|_____________|___________|

这就是我想要的,但是如果我使用新的post_id运行查询:

INSERT INTO post_views (`post_id`, `views`) VALUES (2, 1) ON DUPLICATE KEY UPDATE `views` = `views`+1

我明白了

____________________________________
|          |             |           |
|    id    |   post_id   |   views   |
|__________|_____________|___________|
|          |             |           |
|    1     |     1       |    2      |
|__________|_____________|___________|  
|          |             |           |
|    3     |     2       |    1      |    
|__________|_____________|___________|

id是3而不是2,所以每次我使用相同的post_id运行查询时,就像在插入具有ID的新行一样。

因此,如果我使用post_id = 3运行查询三次,则新闻ID为7。

那是正常的吗?

1 个答案:

答案 0 :(得分:0)

这不是问题。表格中的id并非顺序无间断。确保这种逻辑非常昂贵。它需要锁定整个表以进行插入。明智地,数据库引擎不要这样做。

在单线程环境中-没有并发事务-您可以通过执行单独的updateinsert命令来解决此问题:

update post_views
    set views = views + 1
    where post_id = 1;

insert into post_views (post_id, views)
    select post_id, 1
    from (select 1 as post_id) x
    where not exists (select 1 from post_views pv where pv.post_id = x.post_id);

where甚至阻止insert尝试更新,因此不会生成新的ID。但是,我强烈建议您不要采用这种方法。这不是线程安全的。在并发处理世界中,它不能保证您想要的。

您的情况甚至更陌生。您不需要id中的post_views列。 post_id既可以是主键,也可以是外键:

create table post_views (
    post_id int primary key,
    views int default 0,
    constraint fk_post_views_post_id foreign key (post_id) references posts(id)
);

如果以这种方式设置数据,则将没有ID,也就不会有任何问题。或者,您可以只将views添加到posts表中并处理一个表。