0

列に連続番号を入力したいのですが、単一のシーケンスでは不十分です。この列は、必要に応じて「サブID」のように動作します。テーブル内のレコードのグループの増分ID。

計画は、通常の方法と同じように、トリガーを使用して挿入するときに「シーケンスの次の番号」を取得することsequenceです。ただし、「次の番号」だけでなく、特定の結果セットの「次の番号」である必要があります。

次のサンプルデータについて考えてみます。ここで、display_id列は管理の助けが必要なシーケンスであり、レコードの値に依存していgroup_nameます。

id | group_name | display_id
------------------------------
  5 | GroupA | 3
  4 | GroupA | 2
  3 | GroupA | 1
  2 | GroupB | 2
  1 | GroupB | 1

私はこのクエリのようなクエリを考えて、次の「次の番号」を取得しますGroupA

select max(record_id) + 1
from my_records
where group_name = 'GroupA'

それGroupAは4を返しますが、GroupBそれは3を返します。

もちろん、上記のクエリを使用することはできますが、のアトミックな利点は失われますsequence。そのようなシーケンスを自信を持って管理する方法はありますか?

数字がスキップされる可能性については心配していません(シーケンスのように)。

編集:(
シーケンスの場合と同様に)ロールバックなどが原因で1つか2つが欠落していることに満足しています。ただし、それでも、display_id列が複数のシーケンスを維持する必要があります。

4

2 に答える 2

3

私はそれを強くお勧めしますが(単一のシーケンスを使用し、予想よりも大きなギャップがあることを受け入れることをお勧めします)、独自の疑似シーケンステーブルを作成できます

CREATE TABLE my_sequences (
  sequence_name VARCHAR2(30) PRIMARY KEY,
  sequence_val  NUMBER
);

いくつかの行を挿入します

INSERT INTO my_sequences( sequence_name, sequence_val )
  VALUES( 'GroupA', 1 );
INSERT INTO my_sequences( sequence_name, sequence_val )
  VALUES( 'GroupB', 1 );

次に、次のシーケンス値を取得する関数を記述します

CREATE FUNCTION get_nextval( p_sequence_name IN VARCHAR2 )
  RETURN NUMBER
IS
  l_val NUMBER;
BEGIN
  SELECT sequence_val
    INTO l_val
    FROM my_sequences
   WHERE sequence_name = p_sequence_name
     FOR UPDATE;

  UPDATE my_sequences
     SET sequence_val = sequence_val + 1
   WHERE sequence_name = p_sequence_name;

  RETURN l_val;
END;

これにより、次の行を取得したトランザクションがコミットまたはロールバックするまで、特定のシーケンスのテーブル内の行がロックされます。これにより、一度に1つのセッションのみが特定の行を挿入できるようになり、Oracleシーケンスを使用する場合と比較して、アプリケーションのスケーラビリティが大幅に低下しますgroup_name。他のセッションはシーケンスの待機をブロックします。同時ユーザー数が比較的少ない(または同時ユーザー数が比較的多い)システムの場合group_name値)、それはあなたに受け入れられるかもしれません。しかし、一般的にそれは悪い習慣です。Oracleのバージョンによっては、自律型トランザクションを使用して同時実行性を高めることができる場合がありますが、それによってソリューションがさらに複雑になります。スケーラビリティについて本当に心配している時点で、設計全体を押し戻して、Oracleシーケンスを使用することをお勧めします。

于 2013-02-21T22:00:14.387 に答える
0

列に一意の複合インデックスを作成しgroup_name + display_idます。

次に、コードを使用して、例外がスローされた場合に備えて、次の値の生成を再実行します。

PS:個人的には好きではありませんが、この場合、良い選択肢がない可能性があります

于 2013-02-21T21:42:17.140 に答える