[英]Fill deleted numbers in consecutive series of numbers and LAST_INSERT_ID
First of all I'm an amateur and non-english native speaker, so I would appreciate it if you would have a little patience with me ;)首先,我是一个业余和非英语母语人士,所以如果你对我有一点耐心,我将不胜感激;)
Trying to do two things here and I'm not sure if I should do two questions about it, but since it's all related in my case, I would like to say it all in one question.在这里尝试做两件事,我不确定我是否应该就此做两个问题,但由于这一切都与我的情况有关,我想在一个问题中全部说出来。
I'm making a sort of accounting software, in theory for my personnal use.我正在制作一种会计软件,理论上供我个人使用。 I'm using a DB generated auto_increment ID for almost all my objects, but for some specific cases I need a "parallel" more open ID that won't be primary key but could be manipulated by the user(yeah, I've read lots of questions about "you don't need a consecutive Primary Key", and i understand it and agree, but let me remark that this column won't be the primary key , lets call it just a "human-not-computer-expert friendly ID") matching these conditions:
我几乎所有对象都使用数据库生成的 auto_increment ID,但对于某些特定情况,我需要一个“并行”更开放的 ID,它不会是主键但可以由用户操作(是的,我读过很多关于“你不需要连续的主键”的问题,我理解并同意,但让我说这个列不会是主键,让我们称之为“人而不是计算机-专家友好 ID") 匹配这些条件:
DELETE
s and whatever other operations, so if the user "say yes", the minimum missing ID should be automatically found and used.DELETE
s 和任何其他操作来填充缺失的 ID,因此如果用户“说是”,应该自动找到并使用最小的缺失 ID。 I have no problem with doing this "by hand" in c#, but are there some way to achieve something like this in MySQL directly?我在 c# 中“手动”执行此操作没有问题,但是有什么方法可以直接在 MySQL 中实现这样的功能吗? I've read in the MySQL documentation that
AUTO_INCREMENT
does fulfill my first two conditions, but even if it fills missing deleted numbers by default, which I'm not sure of, I don't want it to do that by default, I need the software to ask first, or at least to do it based on a configuration pre established by the user.我在 MySQL 文档中读到
AUTO_INCREMENT
确实满足我的前两个条件,但即使它默认填充缺失的已删除数字,我不确定,我不希望它默认这样做,我需要软件首先询问,或者至少根据用户预先建立的配置来执行。
Therefore I think I should do it by hand in c#(at least the last part, but i suspect i will be forced to do it entirely), which brings the question about LAST_INSERT_ID
.因此,我认为我应该在 c# 中手动完成(至少是最后一部分,但我怀疑我将被迫完全完成),这带来了关于
LAST_INSERT_ID
的问题。
So, the MYSQL documentation says:所以,MYSQL 文档说:
If the previous statement returned an error, the value of LAST_INSERT_ID() is undefined.
如果前面的语句返回错误,则 LAST_INSERT_ID() 的值未定义。 For transactional tables, if the statement is rolled back due to an error, the value of LAST_INSERT_ID() is left undefined.
对于事务表,如果语句因错误而回滚,则 LAST_INSERT_ID() 的值未定义。 For manual ROLLBACK, the value of LAST_INSERT_ID() is not restored to that before the transaction;
对于手动 ROLLBACK,LAST_INSERT_ID() 的值不会恢复到事务前的值; it remains as it was at the point of the ROLLBACK.
它保持在回滚时的状态。
I understand that LAST_INSERT_ID()
is basically useless if the previous INSERT
statement fails for whatever reason.我知道如果之前的
INSERT
语句因任何原因失败, LAST_INSERT_ID()
基本上是无用的。
If that's the case, there's no way to retrieve the last inserted ID that ensures a known behaviour when something fails?如果是这种情况,有没有办法检索最后插入的 ID 以确保出现故障时的已知行为? Something like when
INSERT
fails returns 0 or a SQL exception?类似于
INSERT
失败时返回 0 或 SQL 异常? And if there's no other way what is the standard way of doing it(I suppose MAX(Id)
won't do it), if something like a standard way exists... or should I just stop trying to do it at one go and do first the updates, check if all went ok, and then do a SELECT LAST_INSERT_ID
?如果没有其他方法,那么标准的做法是什么(我想
MAX(Id)
不会这样做),如果存在类似标准的方法……或者我应该立即停止尝试这样做并首先执行更新,检查是否一切正常,然后执行SELECT LAST_INSERT_ID
?
To sum up:总结:
LAST_INSERT_ID
? LAST_INSERT_ID
怎么回事? Should I give up and don't use it directly?Situation 1, knowing an id that you want inserted into an AUTO_INCREMENT
情况 1,知道要插入
AUTO_INCREMENT
的 id
Honoring that the AI is not a PK as described.尊重 AI 不是所描述的 PK。
-- drop table a12b;
create table a12b
( id varchar(100) primary key,
ai_id int not null AUTO_INCREMENT,
thing varchar(100) not null,
key(ai_id)
);
insert a12b (id,thing) values ('a','fish'); -- ai_id=1
insert a12b (id,thing) values ('b','dog'); -- 2
insert a12b (id,thing) values ('b2','cat'); -- 3
delete from a12b where id='b';
insert a12b(id,ai_id,thing) values ('b',2,'dog with spots'); -- 2 ******** right here
insert a12b (id,thing) values ('z','goat'); -- 4
select * from a12b;
+----+-------+----------------+
| id | ai_id | thing |
+----+-------+----------------+
| a | 1 | fish |
| b | 2 | dog with spots |
| b2 | 3 | cat |
| z | 4 | goat |
+----+-------+----------------+
4 rows in set (0.00 sec)
Situation 2, having a system where you delete rows at some point.情况 2,有一个系统,您可以在某个时候删除行。 And want to fill those explicitly deleted gaps later: See my answer Here
并希望稍后填补那些明确删除的空白: 在此处查看我的答案
Situation 3 (INNODB has a bunch of gaps sprinkled all over):情况 3(INNODB 到处散布着一堆空白):
This was not part of the question.这不是问题的一部分。 Perhaps use a left join utilizing a helper table (at least for ints not varchars. But then again we are talking about ints).
也许使用使用辅助表的左连接(至少对于整数而不是 varchars。但是我们又在谈论整数)。 If you need to spot a gap without knowing, shoot for a left join with a helper table (loaded up with numbers).
如果您需要在不知情的情况下发现差距,请使用辅助表(装有数字)进行左连接。 I know it sounds lame, but helper tables are lean and mean and get the job done.
我知道这听起来很蹩脚,但辅助表精益求精,可以完成工作。 The following would be a helper table: https://stackoverflow.com/a/33666394
以下将是一个辅助表: https : //stackoverflow.com/a/33666394
using the above table with 4 rows, continue with:使用上表的 4 行,继续:
insert a12b (id,thing) values ('z','goat'); -- oops, problem, failed, but AI is incremented behind the scene
insert a12b (id,thing) values ('z2','goat'); -- 6 (you now have a gap)
data:
+----+-------+----------------+
| id | ai_id | thing |
+----+-------+----------------+
| a | 1 | fish |
| b | 2 | dog with spots |
| b2 | 3 | cat |
| z | 4 | goat |
| z2 | 6 | goat |
+----+-------+----------------+
There are a ton of ways to generate gaps.有很多方法可以产生差距。 See This and That
看到这个那个
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.