0

私はこの問題に数時間失敗しましたが、頭を悩ませることができません。「人間」の視点から見るとかなり単純に思えますが、どういうわけかコードに書き込めないようです。

状況: 特定の場所に割り当てられている開始番号と現在の「アクティブな」番号 (または一般的な場所の場合は 0) によって定義されるいくつかの番号範囲が与えられた場合

startno   | actualno | location
100       | 159      | 0
200       | 203      | 1
300       | 341      | 2
400       | 402      | 0

ご覧のとおり、1 つの場所に対して 2 つの範囲が存在する場合もあります。この場合、startno が最も高い範囲 (この場合は 400) のみがアクティブと見なされ、他の範囲は履歴の目的でのみ存在します。

すべてのユーザーは特定の場所 (場所列と同じ ID) に割り当てられますが、一般的な場所 (ゼロ) には割り当てられません。

使用者が新しい番号を必要とするとき、彼は自分の場所に割り当てられた範囲から割り当てられた番号を取得します。何も見つからない場合は、最も高い一般的な番号から割り当てられます (たとえば、user.location = 0 は 403、user.location を取得します)。 = 2 は 342 になります)。

次に、ユーザーは、この番号を使用するか、割り当てられた番号から始まる量 X を使用するかを選択できます。

ここで質問があります: 範囲が互いに重ならないようにするにはどうすればよいでしょうか? ユーザー (場所 = 2) が次の番号 342 を取得し、その後に 100 個の番号が必要であると判断したとします。これにより、一般的な範囲内にある 441 までの終了番号が生成されますが、これは発生してはなりません。

開始番号と終了番号の両方を使用し、MAX() を集計し、テーブル自体を結合して、いくつかのネストされた SELECT を試してみましたが、100% 正しく取得できません。

4

2 に答える 2

0

そのようなことに関する私の理解から、データベースのテーブルにトリガーを作成して検証を行い、アプリケーションがテーブルを更新しているときにオーバーラップが見つかった場合にエラーを発生させることができるので、ユーザーは単にできないというエラーを受け取るだけです。やれ。441 で終了したい場合は、ユーザーにそれを実行させ、actualnoを使用してテーブルを 441 に更新してみてください。次に、単純な選択で、新しい番号を既存のすべてのstartnoと比較し、 startnoよりも大きいかどうかを確認し、エラーを発生させます。更新トリガーで次のようなもの:

IF EXISTS(SELECT 1 FROM 
         Table1
         WHERE @newnumber >= startno AND id <> @currentID)
BEGIN
    'Go Raise the error
END

多分私はここで何かを逃したかもしれません.これはうまくいかない場合があります.

データの整合性チェックにトリガーを使用することは完全に問題なく、まったく問題にはなりません。これは、特にマルチスレッドが大きな問題を引き起こす可能性があると考えている場合は、事前の検証よりもはるかに簡単です。

一方、これがあまりにも簡単に起こらないようにするために、これらの数値に初期値としてゼロをいくつか追加するだけです。

startno   | actualno | location
100000    | 100059   | 0
200000    | 200003   | 1
300000    | 300041   | 2
400000    | 400002   | 0
于 2013-05-02T09:04:25.307 に答える
0

よくあることですが、質問を投稿してからすぐにアプローチを見つけました。問題を説明しているように見えるので、他の人はそれが解決策を得るための途中であることを理解しています. 少なくとも、これまでのところ非常に耐性があることが証明されている可能性のあるものを入手しました。

データベースにクエリを実行します

SELECT nostart FROM numbers
WHERE nostart BETWEEN X AND Y

ここXで、 は要求された開始番号Yで、 はユーザーの終了番号です。(私の導入例に準じてX = 342Y = 441

これにより、開始番号がユーザーが要求した番号の範囲内にあるすべての範囲のリストが表示されます。この場合、リストは次のようになります。

nostart 
400

クエリで結果が見つからない場合、私はゴールデンであり、数値を使用できます。クエリが単一の結果を見つけ、その結果がユーザーの開始番号と等しい場合、ユーザーがこの範囲から何かを要求したのはこれが初めてであることを意味するため、私も問題ありません。

そうでない場合は、その範囲内に別の範囲があるため、その範囲を使用できません。また、クエリで複数の結果が見つかった場合 (たとえば forX = 100Y = 350の場合、100|200|300複数の範囲が重複しているため、リクエストも拒否されます。

誰かがこれに関するより良い解決策やメモを持っている場合は、これをここに残して、うまくいく限り使用します.

于 2013-05-02T12:13:40.687 に答える