4

使用 Symfony2.0、Doctrine 和 MySQL,我需要根据以下格式自动生成相关发票编号:

年/自增

例如,2012 年的发票:

2012/00000001
2012/00000002
2012/00000003

ETC...

该发票编号将使用invoice_number我的 MySQL 数据库中的采购表中的一个字段进行存储。

问题是,我如何查询数据库以返回特定年份的最后一个自增数?

换句话说(伪代码):

function new_invoice(){
    $year = today.year;
    select last invoice_number where year = $year;
    $new_invoice_number = increment invoice_number;
    store $year . "/" . $new_invoice_number;
}

我怎样才能做到这一点?

4

1 回答 1

9

首先,symfony2 和教义2 都不是您的问题和解决方案的一部分。其次,您可能需要考虑将 a 存储/在您的 invoice_number 中,主要是因为您需要为此字段设置一个 varchar,它在索引和查询项目等方面的性能比整数差。

也就是说,您想要的可以通过多种方式实现,具体取决于您的需求:

选择最后一个条目,加一,保存

这是一种解决方案,仅当您没有太多写入购买表或这些写入由一个进程(例如,批处理)完成时才有效,您可以在其中等待一个项目被写入,如果成功写入下一个一。

只需从数据库中选择最后一个条目,获取invoice_number,递增一,保存。如果年份不同,请从一个开始。

当然,如果你每秒有很多写入,你就会遇到麻烦,因为在你写一行的那一刻,另外两个可能已经读取了旧的最后一个 invoice_number,将它加一并尝试存储它(导致错误,因为他们需要是独一无二的)。

读取时动态计算

如果您不需要invoice_number经常使用此解决方案,则此解决方案效果很好。你可以对一个想法有一个正常的 auto_increment 。对于每一年,您将去年的最后一个 id 存储在一些帮助表中。当您读取一行时,您可以通过获取年份、上一年的最后一个 id 并从 auto_increment 中减去它来计算 id。

开销当然是您每次都需要计算发票。根据您实际实现它的方式以及数据库负载是什么,这可能从不明显到非常慢。

让 invoice_number 为空,然后计算

这可以通过许多不同的方式完成,如果您不想摆弄事务等,捕获失败的写入等,这是一个非常简洁的解决方案。这个想法是首先使用空的 invoice_number 存储数据,然后在保存数据时计算 invoice_number 并更新数据集。

您可以将其与之前的想法结合起来,像上面描述的那样计算 invoice_number,然后用这个数字更新数据集,而不是每次都重新计算。您还可以有一个 cronjob 或寻找具有空 invoice_number 的行的东西,以及仅由该 cronjob 使用的助手表中的计数器之类的东西。他拿起计数器,增加它,使用这是数据集的新发票,并保存计数器和数据集。

尝试,重复错误

这是一个丑陋的解决方案,但它可以工作并且在某些情况下可能没问题。您选择最后一个 invoice_number,将其加一,保存当前数据集。如果失败,则重复该过程。你这样做直到你成功储蓄。您需要确保在实际数据库上进行选择(doctrine2 可能会缓存结果,这意味着您始终获取旧数据集,增加相同的数字并因此一遍又一遍地遇到相同的错误)并且如果您有一些 master/从站设置不适用于从站,因为它可能不是最新的。

我不喜欢这个解决方案,但正如所说,这是值得考虑的。

一年一桌

每年可以将数据保存在一个表中。这样你就可以使用 auto_increment。当然,外键会变得混乱,并且在许多表上进行选择并不比只有一张表那么容易。您当然可以引入一个组合所有这些表的视图。

使用存储过程

我从来都不是存储过程的粉丝,主要是因为它将逻辑从应用程序带到数据库,因此更难掌握正在发生的事情(“这个值从何而来?”)。但是您可以有一些存储过程来计算invoice_number并将其与其他值一起存储在INSERT INTO

只需使用 auto_increment

如果你只使用 auto_increment,你会为自己省去很多麻烦。您始终可以将年份保存在另一列中并将两者一起显示。当然,如果您的要求来自产品所有者,这可能是不可能的。但是,如果您有任何方法可以做到这一点,请尝试一下!

...

可能还有更多。这些只是我的想法。

于 2012-11-02T20:47:48.833 回答