我有2个具有一对一关系的表:
post_views table
___________________________________
| | | |
| id | post_id | views |
|________|_____________|___________|
posts table
__________________________________________
| | | | |
| id | title | text | .. |
|________|___________|__________|_________|
将post_id
表中的 post_views
与id
表中的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。
那是正常的吗?
答案 0 :(得分:0)
这不是问题。表格中的id
并非顺序无间断。确保这种逻辑非常昂贵。它需要锁定整个表以进行插入。明智地,数据库引擎不要这样做。
在单线程环境中-没有并发事务-您可以通过执行单独的update
和insert
命令来解决此问题:
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
表中并处理一个表。