根据年份生成唯一和顺序交易ID

时间:2016-02-23 10:38:10

标签: php

我有一个php应用程序,它生成一个唯一的事务ID。但是,我发现有时两个事务具有相同的ID。以下是我的代码。如果我能够知道两个交易同一个transid的原因,我将不胜感激。另外,我希望transid从新年开始时的1开始计算。我不知道该怎么做。

问题1:

<?php 
$db = mysqli_query($connection,"SELECT * FROM tab_requisition");
$nrw = mysqli_num_rows($db);
$refID= ("NR".date("Y").($nrw+1));?>
   <tr>
   <th>Requisition ID:</th>
  <td><input  type="text" name="refid" value="<?php echo $refID;?>"  size="100"  readonly="readonly"/></td></tr>

问题2: 我怎样才能使$ refID从每年年初的1开始计算。如NR20161,NR20162 ..... NR20165000。假设在2016年12月31日结束时,最后一个ID是NR20165000。我希望下一个ID开始于NR20171,NR20172,...... NR2017XXXXX

对于如何防止上述复制并在每年年初重置时,我将不胜感激。

3 个答案:

答案 0 :(得分:2)

$nrw = mysqli_num_rows($db);
$refID= ("NR".date("Y").($nrw+1));?>

那是绝对的否。如果你有一天删除行怎么办?您的下一个ID将会关闭,但它已经存在,这就是您收到该错误的原因。

您无法使用行计数来有效地确定下一个数字应该是什么。

您可以简单地使用自动增量值,您的RDBMS将处理冲突。然后,您可以使用该自动增量值生成字母数字唯一ID。

答案 1 :(得分:1)

创建自己的表&#34; NumberGroups&#34;为此目的,使用以下列:

  • 年份:整数
  • NextNumber:Integer

年初主键。

如果您希望获得一年的下一个数字,请使用以下SQL查询:

insert into NumberGroups(Year, NextNumber) values (2016, LAST_INSERT_ID(1) + 1) on duplicate key update NextNumber = LAST_INSERT_ID(NextNumber) + 1; 
select LAST_INSERT_ID();

mysqli_query()的一次通话中执行此操作,将2016年替换为您想要计数器的年份。然后,这将返回下一个要使用的免费号码,每年从1开始。

它的作用:

它检查表中是否已存在给定年份的行。 如果没有给定年份的行,则插入一个新行,其值为2,NextNumber,LAST_INSERT_ID()设置为1。 如果已存在给定年份的行,则更新现有行,并将该行的NextNumber增加1,记住LAST_INSERT_ID()中的旧值NextNumber。 最后,我们在LAST_INSERT_ID()中设置的值将返回给调用者。

当前方法中的问题是,当多个操作并行运行时,两个可以读取表中的相同行数。如果您需要唯一的计数器,则必须确保并行运行的两个活动不会读取相同的值。您可以通过使用具有正确隔离级别的事务来执行此操作,或者您可以通过读取当前值并在同一个SQL语句中将其递增来执行此操作(如此变体中所示)。

资源:

答案 2 :(得分:1)

加入Hanky Panky的回答。

注意:以下代码未经过测试

year列添加到数据库表(与自动递增唯一ID一起),

当交易实际发生时:

INSERT INTO `tab_requisition` (year, ...) VALUES(YEAR(NOW()), ...)

为事务/记录捕获REAL唯一ID

$ID = mysqli_insert_id ($db);

获取当前年度记录数:

SELECT COUNT(*) FROM `tab_requisition` WHERE `year` = YEAR(NOW()) 
-- below line should take care of raise condition (if another record was added meanwhile)
AND `id` <= '.$ID

生成序列号/参考号

$prefix = 'NR';
$year = date('Y');
$count = str_pad($year_record_count,6,'0', STR_PAD_LEFT);

$refNum = $year . $count;

最后,使用refNum

更新您的记录
UPDATE `tab_requisition` SET `ref_num` = "'.$refNum.'" WHERE id = '.$ID

str_pad用于将您的计数填充到特定长度,这将为排序等产生正确的编号。

而不是

NR20171
NR20172
NR201712
NR2017137

它会变成

NR2017000001
NR2017000002
NR2017000012
NR2017000137

我知道,它需要几次数据库调用,但它可能适合您,具体取决于服务器负载/流量

相关问题