SQLテーブルの列の値を制限したいと思います。たとえば、列の値は「car」、「bike」、「van」のみです。私の質問は、SQLでこれをどのように達成するかです。これをDB側で行うのは良い考えですか、それともアプリケーションに入力を制限させるべきですか。
また、将来的には「トラック」などの値を追加または削除する予定です。
私が使用しているデータベースの種類はSQLiteとMySQLです。
これらの輸送手段を含む新しいテーブルを追加し、列をそのテーブルへの外部キーにします。将来、新しい輸送手段をテーブルに追加することができ、列の定義は同じままです。
この構成では、アプリケーションではなく、DBレベルでこれを規制することを決定的に選択します。
MySQLの場合、ENUMデータ型を使用できます。
column_name ENUM( 'small'、 'medium'、 'large')
MySQLリファレンス:ENUMタイプ を参照してください。
これに加えて、アプリ側ではDB側[〜#〜]と[〜#〜]で制限する方が常に良いと思います。列挙型と選択ボックスがあれば、カバーされます。
はい、チェック制約を追加することをお勧めします。チェック制約は、データベース内のデータの有効性を保証し、データの整合性を提供するために使用されます。それらがデータベースレベルで使用される場合、アプリケーション自体が無効なデータを受け入れても、データベースを使用するアプリケーションは無効なデータを追加したり、有効なデータを変更したりできないため、データは無効になります。
SQLiteの場合:
create table MyTable
(
name string check(name = "car" or name = "bike" or name = "van")
);
MySQLの場合:
create table MyTable
(
name ENUM('car', 'bike', 'van')
);
チェック制約を使用します。 SQL Serverでは、次のように機能します
ALTER TABLE Vehicles
ADD CONSTRAINT chkVehicleType CHECK (VehicleType in ('car','bike','van'));
これがANSI規格であるかどうかはわかりませんが、MySQLにも同様の構造があると確信しています。
DB側の検証を使用する場合は、トリガーを使用できます。 SQLiteの場合は this を、MySQLの場合はthis 詳細なハウツー を参照してください。
したがって、問題は、データベース検証を使用する必要があるかどうかです。複数のクライアントがある場合(それらが異なるプログラムであろうと、複数のユーザー(プログラムのバージョンが異なる可能性がある)であろうと)、データベースルートを使用するのが間違いなく最善です。データベースは(うまくいけば)一元化されているため、検証の詳細の一部を切り離すことができます。特定のケースでは、列に挿入されている値が、有効な値をリストするだけの別のテーブルに含まれていることを確認できます。
一方、データベースの経験がほとんどなく、複数の異なるデータベースをターゲットにすることを計画していて、専門知識を開発する時間がない場合は、おそらく単純なアプリケーションレベルの検証が最も便利な選択です。