试图
创建对INSERT&sets调用的触发器originId = id (AUTO_INCREMENT)
,
我使用了建议的SQLhere in 1st block:
CREATE TRIGGER insert_example
BEFORE INSERT ON notes
FOR EACH ROW
SET NEW.originId = (
SELECT AUTO_INCREMENT
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'notes'
);
由于
information_schema
缓存,我还设置了information_schema_stats_expiry = 0
在
my.cnf
文件中。现在,我注意到,每次插入都会立即更新信息。。但是,通过控制台以大约2分钟的间隔执行“直接”插入,我一直没有更新
AUTO_INCREMENT
中的originId
值。(它们应该等于
id
字段)显式查询时,获取AUTO_u)将导致更新的正确值。
因此我怀疑
SELECT AUTO_INCREMENT...
子查询的结果会以某种方式。。什么?缓存?怎么能避开这个?
谢谢您。
编辑1
我打算用这种方式实现某种风险投资:
用户创建新便笺,app将其标记为“new”,并在MySQL表中执行插入操作。这是“原点”的音符。
然后用户可以在UI中(完全)编辑这个注释,app将其标记为“update”,并再次将其作为新行插入MySQL表中。但这次
originId
应该用id
的“origin”注释(通过app logics)填充。等等。这允许在选择上按
originId
分区,只将最新版本获取到UI。初始问题:
如果“origin”注释的
originId
为空,则MySQL 8窗口函数默认为(且仅限于?)尊重空模式执行的帧不像预期的那样(“好吧,对了,这都是关于按列分组中的空值”)。假设解决方案:
将“origin”注释的
originId
设置为id
在其初始且仅插入时,预期有两个好处:通过
originId
=id
轻松获取“原始”注释,按
originId
执行正确的分区。产生的问题:
id
是自动递增的,所以在通过后端(即PHP)插入时(对于新行)不可能(我知道)获得它的新值。假设解决方案:
所以,我希望找到一些MySQL机制来解决这个问题(避免使用
id
字段进行操作),触发器似乎是一种正确的方法。。。编辑2
我相信在MySQL中自动复制自动递增字段(或任何字段)是非常快速和非常容易的,但现在看来完全不是这样。。
所以,可能更好的方法是让
id
字段负责“关联”注释的版本:在创建和“原点”插入时-用
vcsGroupId UNSIGNED INT
填充它,在“编辑”和“版本”中插入-用“同级/原始”值填充它(用CTE获取),
在“视图”和“正常”中选择-通过
MAX(vcsGroupId) + 1
、vcsGroupId
或timestampPARTITION BY vcsGroupId
执行带窗口功能的成帧,然后仅使用第一行(或升序并使用最后一行),在视图和“原点”选择-几乎相同,但相反。。
看起来比较容易,不是吗?
最佳答案
你在玩火。我不知道你的扳机到底会出什么问题(除此之外,它对你已经不起作用了),但我有一种强烈的感觉,很多事情都会出问题。例如:如果在一个语句中插入多行,会怎么样?我不认为引擎会为每一行更新information_schema
。如果运行INSERT ... SELECT
语句,情况会更糟。因此,将information_schema
用于此任务是一个非常糟糕的主意。
然而,第一个问题是:你为什么需要它?如果需要保存“origin ID”,那么您可能计划更新id
列。这已经是个坏主意了。假设你能找到解决问题的方法-什么能保证你,触发器之外的originId
不会改变?
但是-另一种方法是在插入时保持originId
列为空,并在更新触发器中更新它。
假设这是你的桌子:
create table vcs_test(
id int auto_increment,
origin_id int null default null,
primary key (id)
);
第一次更改原始ID时,使用更新触发器保存原始ID:
delimiter //
create trigger vcs_test_before_update before update on vcs_test for each row begin
if new.id <> old.id then
set new.origin_id = coalesce(old.origin_id, old.id);
end if;
end;
delimiter //
然后,您的选择查询将如下所示:
select *, coalesce(origin_id, id) as origin_id from vcs_test;
见demo on db-fiddle
您甚至可以使用以下架构保存完整的id历史记录:
create table vcs_test(
id int auto_increment,
id_history text null default null,
primary key (id)
);
delimiter //
create trigger vcs_test_before_update before update on vcs_test for each row begin
if new.id <> old.id then
set new.id_history = concat_ws(',', old.id_history, old.id);
end if;
end;
delimiter //
以下测试
insert into vcs_test (id) values (null), (null), (null);
update vcs_test set id = 5 where id = 2;
update vcs_test set id = 4 where id = 5;
select *, concat_ws(',', id_history, id) as full_id_history
from vcs_test;
会回来的
| id | id_history | full_id_history |
| --- | ---------- | --------------- |
| 1 | | 1 |
| 3 | | 3 |
| 4 | 2,5 | 2,5,4 |
View on DB Fiddle
关于mysql - MySQL 8-在INSERT上触发-VCS的重复AUTO_INCREMENT ID,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58122151/