2011-03-27 4 views
17

私はPostgreSQLのテーブルがある場合:PostgreSQLで1アウトオブ2 NOT NULL制約を追加する

create table Education ( 
    id     integer references Profiles(id), 
    finished   YearValue not null, 
    started    YearValue, 
    qualification  text, 
    schoolName   text, 
    studiedAt   integer references Organizations(id), 
    primary key (id) 
); 

は、私はどちらかschoolNameまたはstudiedAtニーズがnullでないためになるように制約を加える必要があります(そのうちの1人は情報を持っていなければなりません)。

どうすればよいですか?

答えて

26

check constraintなどを使用できます。

constraint chk_education check (schoolName is not null or studiedAt is not null) 

マニュアルから:

チェック制約が最も一般的な制約タイプです。これにより、特定の列の値がブール(真理値)式を満たす必要があることを指定できます。

編集:Pithyless'の解釈を遵守するための代替:

constraint chk_education check ((schoolName is not null and studiedAt is null) or (schoolName is null and studiedAt is not null)) 
+1

このチェックは、schoolNameとstudiesAtの両方が設定されていることを防ぎません。私はOPも考えていたと思います。 – pithyless

+0

質問は、少なくとも「schoolName」と「learnedAt」には何らかの情報が含まれていることを強制する不変式を求めます。私はあなたのコメントに従う制約の変形を追加しましたが、私は質問の解釈に同意しません。 –

+2

これは少し遅いですが、これはXOR制約なので、 'CHECK((schoolName IS NULL)<>(learnedAt IS NULL))'と表現することができます) ' – norcalli

0

ます。また、更新時にトリガーを使用してテーブルにデータを許可する前に、ルールが守られていることを確認するために挿入することができます。チェック制約がより複雑なロジックを必要とする場合は、通常このタイプのアプローチを使用します。

+1

注意:制約を強制的にトリガー –

+0

トリガーを使うよりも制約を執行しないほうがいいと言っています。トリガーを使用する場合は、常にパフォーマンスを念頭に置いて、賢明に使用してください。それらの地獄のためにそれらを使用しないでください。特定のニーズをテストし、ニーズを満たすことができる場合はそれを検討してください。トリガを使用しても本質的な悪はありません。それは箱の中の別のツールです。 – Kuberchaun

+0

これは[以前議論されている]と思います(http://stackoverflow.com/questions/460316/are-database-triggers-evil)。私の不満は、既存のデータにルールを適用しないことであり、発火させずにデータを取得する方法がしばしばあります(Oracleのsql *ローダーなど)。そのため、明確に定義されたトランザクションを持つAPIは、副作用がなくてもデータの整合性を提供します(さらに多くの利点があります) –

関連する問題