在连续的数字系列中填写已删除的数字和LAST_INSERT_ID

时间:2016-10-15 09:07:30

标签: c# mysql

首先,我是业余和非英语母语人士,所以如果你对我有点耐心,我会很感激;)

试着在这里做两件事,我不确定我是否应该对它做两个问题,但由于这一切都与我的情况有关,我想在一个问题中说出这一切。

我正在制作一种会计软件,理论上是为了我的个人用途。我正在为几乎所有的对象使用DB生成的auto_increment ID,但是对于某些特定情况,我需要一个“并行”更开放的ID,它不是主键但可以被用户操纵(是的,我读过关于“你不需要一个连续的主键”的很多问题,我理解并同意,但是请注意,这个专栏不会是主键,让我们称之为符合这些条件的“人 - 非计算机专家友好ID”:

  • 如果没有给出参数,则ID应自动递增。
  • 当一个数字作为参数给出时,如果没有占用则应使用该数字,如果被占用则抛出异常。
  • 应询问用户他/她是否想要通过DELETE和其他任何操作填写缺失的ID,因此如果用户“说是”,则应自动找到并使用最小缺失ID。

我在c#中“手动”执行此操作没有任何问题,但有没有办法直接在MySQL中实现这样的功能?我在MySQL文档中读到AUTO_INCREMENT确实满足了我的前两个条件,但即使它默认填充缺少的已删除数字,我也不确定,我不希望它通过默认情况下,我需要首先询问软件,或者至少根据用户预先建立的配置来执行此操作。

因此我认为我应该在c#手工完成(至少在最后一部分,但我怀疑我将被迫完全这样做),这带来了关于LAST_INSERT_ID的问题。

所以,MYSQL文档说:

  

如果前一个语句返回错误,则LAST_INSERT_ID()的值未定义。对于事务表,如果由于错误而回滚语句,则LAST_INSERT_ID()的值未定义。对于手动ROLLBACK,LAST_INSERT_ID()的值不会恢复到事务之前的值;它仍然像ROLLBACK那样。

据我所知,如果之前的LAST_INSERT_ID()语句因任何原因失败,INSERT基本无用。

如果是这种情况,那么无法检索最后插入的ID,以确保在出现故障时的已知行为?像INSERT失败时返回0或SQL异常的东西?如果没有别的办法是什么标准的做法(我认为MAX(Id)不会这样做),如果存在类似标准方式的东西......或者我应该停止尝试在一个首先进行更新,检查一切是否正常,然后进行SELECT LAST_INSERT_ID

总结一下:

  • 是否有某种方法可以直接在MySQL中实现满足给定条件的连续数列?
  • LAST_INSERT_ID有什么用?我应该放弃而不是直接使用它吗?

1 个答案:

答案 0 :(得分:1)

情况1,知道要插入AUTO_INCREMENT

的ID

表示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)

情况2,有一个系统可以在某个时刻删除行。并希望稍后填写明确删除的差距:请参阅我的回答Here

情况3(INNODB散布着一大堆空白):

这不是问题的一部分。也许使用一个使用帮助表的左连接(至少对于不是varchars的int。但是我们再次谈论的是int)。如果您需要在不知情的情况下发现间隙,请使用辅助表(加载数字)进行左连接。我知道这听起来很蹩脚,但帮助表很精简,意味着完成工作。以下是帮助表:https://stackoverflow.com/a/33666394

INNODB Gap Anomaly

使用上面的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           |
+----+-------+----------------+

有很多方法可以产生差距。请参阅ThisThat