3つの可能な文字列のうちの1つだけを持つべきテキスト列があります。制約を課すには、別のテーブルを参照する必要があります。代わりに、別のテーブルを参照せずに、制約の値を列に直接配置できますか?
3 に答える
これがSQLServer、Oracle、またはPostgreSQLの場合、はい、を使用できますcheck constraint
。
MySQLの場合、check constraint
sは認識されますが、強制されません。ただし、を使用することはできますenum
。カンマ区切りのリストが必要な場合は、を使用できますset
。
ただし、これは保守が容易ではないため、一般的に眉をひそめています。ルックアップテーブルを作成し、それを通じて参照整合性を確保するのが最善です。
他の人が言及している CHECK 制約と ENUM データ型に加えて、目的の制限を適用するトリガーを作成することもできます。
良い解決策としてトリガーを必ずしも推奨するわけではありません。参照テーブルを参照しないという基準を満たす別のオプションを指摘しているだけです。
私の習慣は、制約やトリガーを使用する代わりにルックアップ テーブルを定義することです。これは、ルールが単純に列を有限の値セットに制限することである場合です。ルックアップ テーブルに対するチェックのパフォーマンスへの影響は、CHECK 制約またはトリガーを使用する場合よりも悪くはありません。値のセットが時々変更される可能性がある場合は、管理がはるかに簡単です。
また、一般的なタスクは、許可された値のセットを照会することです。たとえば、ユーザー インターフェイスのフォーム フィールドに入力します。許可された値がルックアップ テーブルにある場合、これは、CHECK 制約または ENUM 定義のリテラル値のリストで定義されている場合よりもはるかに簡単です。
「IDなしでルックアップを正確に行う方法」を再コメントしてください
CREATE TABLE LookupStrings (
string VARCHAR(20) PRIMARY KEY
);
CREATE TABLE MainTable (
main_id INT PRIMARY KEY,
string VARCHAR(20) NOT NULL,
FOREIGN KEY (string) REFERENCES LookupStrings (string)
);
MainTable.string
参照整合性によって無効な値が防止されるため、無効な値がないことが保証されます。LookupStrings
ただし、クエリを実行するときに、文字列を取得するためにテーブルに参加する必要はありませんMainTable
。
SELECT main_id, string FROM MainTable;
見る?参加しません!しかし、文字列値を取得します。
複数の外部キー列について再コメントします。
2 つの個別の外部キーを持つことができ、それぞれがルックアップ テーブル内の異なる行を指す可能性があります。外部キー列は、参照されるテーブルの列と同じ名前にする必要はありません。
私の一般的な例は、バグ追跡データベースです。バグは 1 人のユーザーによって報告されましたが、別のユーザーによって修正されるように割り当てられました。reported_by
とは両方とも、テーブルassigned_to
を参照する外部キーです。Accounts
CREATE TABLE Bugs (
bug_id INT PRIMARY KEY,
reported_by INT NOT NULL,
assigned_to INT,
FOREIGN KEY (reported_by) REFERENCES Accounts (account_id),
FOREIGN KEY (assigned_to) REFERENCES Accounts (account_id)
);
Oracle
、SQL Server
およびでは、拘束PostgreSQL
を使用します。CHECK
CREATE TABLE mytable (myfield INT VARCHAR(50) CHECK (myfield IN ('first', 'second', 'third'))
では、次のデータ型MySQL
を使用します。ENUM
CREATE TABLE mytable (myfield ENUM ('first', 'second', 'third'))