PHP&;MySQL:如何创建唯一的“年-月数”键?
我必须为发票创建唯一的id。每个发票id的格式为PHP&;MySQL:如何创建唯一的“年-月数”键?,php,mysql,innodb,auto-increment,Php,Mysql,Innodb,Auto Increment,我必须为发票创建唯一的id。每个发票id的格式为年-月编号,由发票的当前年份和月份以及从1开始的递增编号组成(不允许有间隙) 例如,如果我们在2017年1月有4张发票,我将有以下4张发票id: 2017-1-1 2017-1-2 2017-1-3 2017-1-4 现在我想创建一个应用程序来创建这些唯一的id。特别是,我想确保即使两个人同时请求一个发票号码,他们也应该得到不同的id 我正在使用InnoDB,我有下表 书籍 year | month | number | ---------
年-月编号
,由发票的当前年份和月份以及从1开始的递增编号组成(不允许有间隙)
例如,如果我们在2017年1月有4张发票,我将有以下4张发票id:
2017-1-1
2017-1-2
2017-1-3
2017-1-4
现在我想创建一个应用程序来创建这些唯一的id。特别是,我想确保即使两个人同时请求一个发票号码,他们也应该得到不同的id
我正在使用InnoDB,我有下表
书籍
year | month | number |
------------------------
2017 | 7 | 2 |
2017 | 6 | 5 |
2017 | 5 | 6 |
如果未为年-月
对创建发票,则数据库中没有条目。主键是年-月
对,数字
是一个自动递增索引
假设我计算下一个发票id,如下所示:
$stmt = $db->prepare('INSERT INTO book(year,month,number)
VALUES (?,?,1)
ON DUPLICATE KEY UPDATE number= LAST_INSERT_ID(number+1)');
$stmt->bind_param('ii', $year, $month);
$stmt->execute();
echo 'Next invoice id: ' . $year . '-' . $month . - . $db->insert_id;
说明:$db->insert\u id
返回列号,因为它是一个自动递增列
和最后插入的ID(数字+1)
增加了最后插入的号
(也可能是由其他用户插入的?我不确定,在文档中查找时遇到问题)
这段代码真的有效吗?或者如果人们同时执行这段代码,它可能会创建多个相同的id吗
编辑
假设当前月/年的数量为5。
为什么两个人不可能同时计算一张发票,以便两个查询同时将数字5升级到6?在这种情况下,他们都会得到发票id“2017-11-6”,对吗 对于这样的问题,您可以打开两个终端窗口并使用mysql客户端来尝试
mysql1> select * from book;
+------+-------+--------+
| year | month | number |
+------+-------+--------+
| 2017 | 5 | 5 |
+------+-------+--------+
在两个并发会话中启动事务:
mysql1> begin;
mysql2> begin;
会话1执行IODKU并增加数字(但尚未提交,因为begin
隐式地将我们带出自动提交模式):
由于可重复读取事务隔离,会话2仍然可以看到原始的数值。但一旦它尝试执行自己的增量,它就会等待,因为会话1仍然锁定了行
mysql2> select * from book;
+------+-------+--------+
| year | month | number |
+------+-------+--------+
| 2017 | 5 | 5 |
+------+-------+--------+
mysql12> insert into book values (2017, 5, 0)
on duplicate key update number = last_insert_id(number+1);
-- waits for lock
在会话1中提交:
mysql1> commit;
现在会话2中的IODKU结束了,我们可以看到它第二次增加了这个数字:
mysql2> select * from book;
+------+-------+--------+
| year | month | number |
+------+-------+--------+
| 2017 | 5 | 7 |
+------+-------+--------+
你没有AI专栏吗?如果没有,您应该这样做,因为这将自动使所有记录都唯一。@Fred ii-
number
字段是一个AI
列,但我会随着更新而增加它。您不必为它增加AI,它会自行增加。我觉得我没有完全理解你想在这里做什么。你能在查询中添加mysqli\u error($db)
并查看返回的结果吗?@Fred ii-你是对的,这是使用AI
字段的一种非常不寻常的方式。但是字段number
只是一个AI
键,因此它由$db->insert\u id返回代码>。事实上,它甚至不是独一无二的。可以同时在数据库中显示2017-7-2
和2017-8-2
。但是2017-7-2
和2017-7-3
是不可能的。我在这里发现了这个技巧(),但我不确定它是否会给两个不同的用户提供相同的发票id。嗯……-001
等是否与number
列相关?和数字是一个自动递增索引
不会以前导零递增,因此您可能需要找到另一种方法(我以前在某个地方见过这种方法),并为其添加另一列,id
作为AI,并删除/更改当前的AI列。也许我没有收到你的问题/相关列和00X\u integer
,所以我可能无法在这方面提供更多帮助,对不起,亚当。希望我能在这方面多帮点忙。看看其他人是否能提供(另一)帮助。注意,这样您就不会在第一次插入时设置最后一次插入\u ID
。为了解决这一问题,应该将其插入账面价值(2017年5月,最后一次插入id(1))…
谢谢,这也是对您2016年7月最后一次回答的一个很好的补充:P。我想我需要更深入地了解为什么$stmt=$db->prepare$stmt->execute
与mysql1>begin;相同。。。mysql1>提交代码>。但可以肯定的是,如果没有innodb,这是行不通的,对吗事实上,现在我可以测试它了:D.@Adam与mysqli
的交易,你应该使用and.@PaulSpiegel-tahnk!你也知道一些基本的文献,涵盖了这类东西,并且比文献更容易阅读吗?@Adam,我不是从一本书中学到这一点的。首先我获得了计算机科学学位。然后我读了很多文档。然后我用逻辑来做实验来检验我的理解。20年来,我一直在互联网上回答像你这样的问题。这需要时间,但没有比这更好的学习方法了。
mysql2> select * from book;
+------+-------+--------+
| year | month | number |
+------+-------+--------+
| 2017 | 5 | 7 |
+------+-------+--------+