4

Symfony2.0、Doctrine、および MySQL を使用して、次の形式に従って相関する請求書番号を自動的に生成する必要があります。

年/自動インクリメント

たとえば、2012 年の請求書:

2012/00000001
2012/00000002
2012/00000003

等...

請求書番号はinvoice_number、MySQL データベースの Purchase テーブルのフィールドを使用して保存されます。

問題は、データベースにクエリを実行して、特定の年の最後の自動インクリメント可能な数値を返すにはどうすればよいかということです。

言い換えれば(疑似コード):

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 も doctrine2 も問題と解決策の一部ではありません。/次に、 invoice_number にa を格納することを検討したい場合があります。これは主に、フィールドを varchar にする必要があるためです。これは、アイテムのインデックス作成やクエリなどで整数よりもパフォーマンスが低下します。

とはいえ、必要に応じて、さまざまな方法で目的を達成できます。

最後のエントリを選択し、1 つ増やして保存します

これは、購入テーブルへの書き込みがそれほど多くない場合、またはこれらの書き込みが 1 つのアイテムが書き込まれるのを待つことができる 1 つのプロセス (バッチなど) によって行われ、これが成功した場合に次の書き込みを行う場合にのみ機能するソリューションです。 1。

データベースから最後のエントリを選択し、 を取得しinvoice_number、1 ずつインクリメントして保存します。年が異なる場合は、年から始めてください。

もちろん、1 秒あたりの書き込み数が多い場合は、行を書き込んだ瞬間に、他の 2 人が古い最後の送り状番号を読み取って、それを 1 増やして保存しようとしている可能性があるため、問題が発生します (必要なためエラーが発生します)。ユニークであること)。

読み取り時に動的に計算する

このソリューションは、それほど頻繁に必要としない場合にうまく機能しますinvoice_number。アイデアに対して通常の auto_increment を使用できます。毎年、昨年の最後のIDをいくつかのヘルパーテーブルに保存します。行を読み取るときに、年、つまり昨年の最後の ID を取得して ID を計算し、それを auto_increment から差し引くことができます。

オーバーヘッドはもちろん、毎回請求書を計算する必要があることです。実際の実装方法とデータベースの負荷に応じて、これは目立たないものから非常に遅いものまでさまざまです。

計算するよりも、invoice_number を空にします

これはさまざまな方法で行うことができ、トランザクションなどをいじったり、失敗した書き込みをキャッチしたりしたくない場合は、非常に優れたソリューションです。アイデアは、最初に空のinvoice_numberでデータを保存し、次にデータが保存されたときにinvoice_numberを計算し、データセットを更新することです。

これを前のアイデアと組み合わせて、上記のようにinvoice_numberを計算し、毎回再計算するのではなく、この番号でデータセットを更新できます。また、cronjob などで、invoice_number が空の行を探したり、この cronjob だけが使用するヘルパー テーブルのカウンターのようなものを使用したりすることもできます。彼はカウンターを取得してインクリメントし、これをデータセットの新しい請求書として使用し、カウンターとデータセットの両方を保存します。

試して、エラーで繰り返す

これは醜い解決策ですが、うまくいき、場合によっては問題ないかもしれません。最後のinvoice_numberを選択し、それを1つ増やして、現在のデータセットを保存します。失敗した場合は、プロセスを繰り返します。保存に成功するまでこれを行います。実際のデータベースで必ず select を実行する必要があります (doctrine2 は結果をキャッシュする可能性があります。つまり、常に古いデータセットを取得し、同じ数をインクリメントして、同じエラーが何度も発生する可能性があります)。スレーブが最新ではない可能性があるため、スレーブのセットアップはスレーブで機能しません。

私はこの解決策が好きではありませんが、前述のように、検討する価値のあるものです。

1年に1テーブル

1 年に 1 つのテーブルにデータを保存することが可能です。このようにして、auto_increment を使用できます。もちろん、外部キーが台無しになり、多くのテーブルを選択することは、テーブルが 1 つしかない場合よりも簡単ではありません。もちろん、このすべてのテーブルを組み合わせたビューを導入することもできます。

ストアド プロシージャを使用する

私はストアド プロシージャのファンではありませんでした。主な理由は、アプリケーションからデータベースへのロジックが必要になり、何が起こっているのかを把握するのが難しくなるためです (「この値はどこから来ているのか?」)。invoice_numberただし、 を計算し、それを他の値とともに保存するストアド プロシージャを使用することもできます。INSERT INTO

auto_increment を使用するだけです

auto_increment を使用するだけで、多くの手間を省くことができます。いつでも年を別の列に保存して、2 つを一緒に表示できます。もちろん、あなたの要求が製品所有者からのものである場合、これは不可能かもしれません。しかし、これを行う方法があれば、試してみてください。

...

もっとたくさんあるかもしれません。これらは私の頭のてっぺんからのものです。

于 2012-11-02T20:47:48.833 に答える