使用Symfony2.0、Doctrine和MySQL,我需要根据下面的格式自动生成相关的发票编号:
年份/可自动递增
例如,2012年的发票:
2012/00000001
2012/00000002
2012/00000003等等。
该发票号将使用我的MySQL数据库中的Purchase表中的invoice_number字段进行存储。
问题是,我如何查询数据库以返回某个年份的最后一个可自动递增的数字?
换句话说(伪代码):
function new_invoice(){
$year = today.year;
select last invoice_number where year = $year;
$new_invoice_number = increment invoice_number;
store $year . "/" . $new_invoice_number;
}我该怎么做呢?
发布于 2012-11-03 04:47:49
首先,symfony2和doctrine2都不是您的问题和解决方案的一部分。其次,你可能想要考虑在你的invoice_number中存储一个/,主要是因为你需要将这个字段设置为varchar,这在索引和查询条目之类的东西上表现得比整数差。
也就是说,您想要的东西可以通过多种方式实现,具体取决于您的需求:
选择最后一个条目,递增1,保存
这是一个解决方案,只有当您没有那么多的写入到您的采购表中,或者这些写入由一个进程(例如,批处理)完成时,这种解决方案才有效,其中您可以等待写入一个项目,如果成功,则写入下一个项目。
只需从数据库中选择最后一个条目,获取invoice_number,递增1,保存。如果年份不同,就从一年开始。
当然,如果您每秒有很多次写入,您就会遇到麻烦,因为在您写入一行的那一刻,其他两个可能已经读取了旧的最后一个invoice_number,将其递增1并试图存储它(导致错误,因为它们需要是唯一的)。
读取时动态计算
如果您不经常需要invoice_number,则此解决方案效果很好。你可以在一个想法上有一个普通的auto_increment。对于每一年,您都将上一年的最后一个id存储在某个helper表中。读取行时,可以通过获取年份和去年的最后一个id来计算id,然后从auto_increment中减去它。
开销当然是您每次都需要计算发票。根据您实际实现它的方式和数据库负载,这可能是不明显的,也可能是非常慢的。
让invoice_number为空,然后计算
这可以通过许多不同的方式来完成,如果你不想摆弄事务和类似的东西,捕捉失败的写入等等,这是一个非常简洁的解决方案。其思想是首先使用空的invoice_number存储数据,然后在保存数据时计算invoice_number并更新数据集。
您可以将其与前面的想法结合起来,像上面描述的那样计算invoice_number,然后用这个数字更新数据集,而不是每次都重新计算它。您还可以有一个cronjob,或者查找具有空invoice_number的行,以及类似于helper表中的计数器的东西,它只由这个cronjob使用。他拿起计数器,递增它,使用这是数据集的新发票,并保存计数器和数据集。
尝试,在出现错误时重复
这是一个丑陋的解决方案,但它是有效的,在某些情况下可能还可以。您选择最后一个invoice_number,将其递增1,保存当前数据集。如果失败,则重复该过程。你一直这样做,直到你成功地存钱。您需要确保在实际数据库上执行select (doctrine2可能会缓存结果,这意味着您会一直获取旧的数据集,递增相同的数字,从而一次又一次地命中相同的错误),如果您有一些主/从设置不能在从数据库上工作,因为它可能不是最新的。
我不喜欢这个解决方案,但正如我所说的,它是值得考虑的。
每年一张表
每年可以将数据保存在一个表中。这样你就可以使用auto_increment了。当然,外键变得混乱了,在多个表上进行选择并不像只有一个表那么容易。当然,您可以引入一个结合了所有这些表的视图。
使用存储过程
我从来不喜欢存储过程,主要是因为它需要从应用程序到数据库的逻辑,这使得理解发生了什么变得更加困难(“这个值来自哪里?”)。但是您可以使用一些存储过程来计算invoice_number,并将其与其他值一起存储在INSERT INTO上
只需使用auto_increment即可
如果你只使用auto_increment,你就省去了很多麻烦。您始终可以将年份保存在另一列中,并将这两个列一起显示。当然,如果您的需求来自产品所有者,这可能是不可能的。但是如果你有任何方法可以做到这一点,那就试试吧!
...
可能还有更多。这些都是我想出来的。
https://stackoverflow.com/questions/13202382
复制相似问题