質問: 会員登録のWebフォームで、以下のOracleのテーブルに登録する状況についてのご質問です。 id name ------------------ 1 doraemon 2 nobita 3 jyaian 4 doraemon idは、連番でシーケンスで採番されます。 nameは、名前です。ここは、既に同じ名前が存在したら登録NGとしたいです。 ただ、既にテーブルにはdoraemonが重複して登録されています。 これはOKで、Webからの登録の場合、重複NGとしたいです。 テーブルのnameが完全にユニークであれば、ユニーク制約をいれれば 重複して登録できないようにできますが、 上記のとおり、すでに名前があるのでユニーク制約をいれられません。 この状況で、複数人が、同時に、suneoと入力したときに、 エラーとしたいのですが、なにか方法ありますでしょうか。
回答: プログラムで行う場合とデータベースの排他制御機能で行う方法が考えられます。 データベースがOracleとのことですので、Oracleの場合の例を記載させていただきます。 まず、手順を考えると 1)ユーザが指定したnameがすでに登録されているかSELECTで検索 SELECT count(name) from table where name='suneo' 2)1)の結果、まだ登録されていなければINSERTで登録 INSERT into table values(val,'suneo') となるかと思います。 この1)と2)の操作の間に他のアクセスを禁止すれば良いため、 SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;で事前に排他制御を設定 1),2)を発行(1)の結果登録済みの場合はROLLBACK;でトランザクションを 終了しないとデッドロックが発生する可能性があります) COMMIT;コミットしトランザクション終了 となります。 排他制御については が参考になるかと思います。 Javaなどのクラスベース言語の場合、1)2)を行うクラスをSingletonとし、 メソッドをsyncronizedにすることで実現可能です(他のアプリケーション等からの アクセスがない場合のみ)