2010-12-08 12 views
1

フィールドに「smth」、「smth else」または「もう1つのもの」を持つエントリを作成することをユーザーが制限する(Oracleで)制約を追加しようとしています。基本的に、それは私がそれを書くだろう方法は次のとおりです。チェックSQLステートメントのネストされたクエリ

ALTER TABLE sometable 
ADD CONSTRAINT sometable_text_chk 
CHECK (
    caption IN ( 
     SELECT caption 
     FROM sometable 
     WHERE text NOT IN ('smth', 'smth else', 'one more thing') 
    ) 
) 

残念ながら、この機会に巣クエリに許可されていないことのようです。おそらく回避策はありますか?

+0

これはあまり明確ではありません。フィールド 'text'と' caption'の関係はどうですか? 'あなたがエントリを作成することからユーザを制限すると言うとき、あなたはどういう意味ですか?フィールド内に既に存在する? (あなたはフィールド 'キャプション'でユニークな値を持ってほしいと話していますか?) – Unreason

答えて

2

基本的に、別のテーブルのデータに基づいて、あるテーブルのデータの有効性に関する一般的なチェックを行っています(注:実際には、OPが質問を明確にするのを待っていません)。一般的なケースのための

  • - あなたが使用して、かなり多くの内部(更新クエリの最も単純なため停止してデータベースをもたらすなどの複雑なデータ検証の面でトリガ行うことができます。

    回避策のいずれかであります(より代表的な例が役に立ちました) - 検証の 'スナップショット'を使ってCHECK制約を動的に維持することができます(これは沸騰しますチェックステートメントの中で参照されているテーブルのコピーを保持することになるので、それはかなり醜いです)

  • おそらく、あなたは外部キーチェックを行うことができます。これはデータベースの設計方法ではありませんが、意味的に見れば、このテーブルと他のエンティティとの関係が(あなたのCHECKで)主張することになります。そのエンティティが別のテーブルとして実現されていない場合、多分それはあったはずですか? (これらの種類の問題はときどき悪いデザインの指標)
0

あなたはこのようなCHECK制約を追加することはできません、あなたは可能な値のリスト全体を提供文字通り必要があります。

CHECK (caption IN (Word1, Word2, Word3 ...)) 

あなたは他の方法で行うことができますしかし:

CHECK (Caption <> 'smth' and caption <> 'smth else' and caption <> 'one more thing') 

しかし、あなたはからチェックを失いましたsometable。

1
ALTER TABLE sometable 
ADD CONSTRAINT sometable_text_chk 
CHECK (text not in ('smth', 'smth else', 'one more thing')) 
/

ありがとうございます。

+0

これは私が最初に思ったものですが、要件はもう少し複雑です...ルックアップテーブルの値を探す必要があります。キー自体 –

+0

しかし、アレックスは具体的に "sometable"を2回述べました。そして、指定されたスキーマがなければ、それは同じテーブルのみである可能性があります。あなたは正しいかもしれませんが、私はあなたが行間をどのように読むことができるかに感心しています:-)。 –

0

私はこれが過度かもしれないと認めます。あなたは高速リフレッシュを作成することができた場合は、リフレッシュ・オン・コミット(多分何か以下のように)、あなたのテーブルに不正な値の数を数えるだろうな定義でのマテリアライズド・ビュー:

select count(*) as rows_with_errors 
    from data_table a 
    join lookup_table b on(a.caption = b.caption); 

クエリが返す必要がありますこれは、data_tableの値にlookup_tableの値が含まれていない可能性があるためです。次に、マテリアライズド・ビュー自体にCHECK制約(rows_with_errors = 0)を作成します。

更新または挿入がdata_tableにコミットされるたびに、マテリアライズド・ビューがリフレッシュされます。ただし、lookup_tableに存在するdata_tableに値を入力すると、カウント(*)はゼロ以外の値を返し、マテリアライズド・ビューのチェック制約が失敗するため、全体挿入/更新ステートメントは失敗/ロールバックします。 Voila!

関連する問題