2016-02-23 30 views
0

我有一个生成唯一交易ID的php应用程序。但是,我发现有时两个交易具有相同的ID。以下是我的代码。如果我可以知道原因,同时给予两次交易相同的转账,我会感激。另外,我希望转账在新年伊始从1开始计算。我不知道该怎么做。根据年份生成唯一的序列交易ID

问题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.I想要下一个以NR20171,NR20172开始...... NR2017XXXXX

我会很感激任何回应如何防止重复以上并在每年年初重置。

+0

显示您的sql表 –

回答

1

与下面的列为此创建自己的表 “NumberGroups”:

  • 年份:整数
  • NextNumber:整数

与上年主键。

然后,如果您想获得下一编号为一年,使用下面的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语句中增加它来完成它(如同这个变体)。

资源:

+0

请问,这是问题1或2的解决方案。因为它似乎是quest2。请澄清。这个电话是用于交易ID还是什么? – Dave

+0

这是针对这两个问题。 SQL查询将返回一个可用于构建事务ID的数字。 – NineBerry

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

这绝对没有不行号如果你有一天删除行?你的下一个ID将会下降,但它已经存在了,这就是你得到这个错误的原因。

您不能使用行数有效地决定下一个数字应该是多少。

您可以简单地为此使用自动增量值,您的RDBMS将负责处理碰撞。然后,您可以使用该自动增量值生成您的字母数字唯一ID。

+0

你的意思是我应该在我的数据库中创建一个字段,这个字段会自动增加,或者当一个记录插入到DB中时,我会自动增加它。我已经有一个id作为自动增量DB,它总是主键 – Dave

1

要添加到手帕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 

我知道,这需要几个数据库调用,但它可能为你工作,这取决于服务器负载/交通

+0

请理解,这个trasactionID将在打开只读页面时生成。当事务值尚未插入到行中时,如何执行插入到数据库?另外,是否必须添加填充? – Dave

+0

@Dave 1)我看不出如何有事件/事务的ID没有发生。 “交易”是什么意思,页面加载? 2)我认为填充是有道理的,没有什么是真正的强制,只是良好的做法。 –

+0

我在这里指的交易ID只是一个参考ID,用于唯一标识该行。因此,我需要从数据库中获取它,它将在窗体上显示为Readonly,期望用户填充其他部分表单填写完成后,数据将被提交给数据库。 – Dave