C99では、整数型のサイズ/ドメインについてかなり明確にできます。
OracleやPostgresqlなどのSQLデータベースをCプログラムからインターフェースする場合、クライアントのものと一致する整数型のテーブルを作成したいと思います。
たとえば、人工主キー列のようなシーケンスのint64_t、uint64_t、uint32_tなどを照合します。
NUMBERを使用するだけで、オーバーフロー/アンダーフローが発生したり、クライアント言語で表現できないデータが可能になりますよね?
そのような列を正しく定義する方法は?
モチベーション
なんでそんなことしたいの?信頼できるソフトウェアを書きたいからです。データベースクライアントアプリケーションを設計し、必要なIDが2 ^ 32未満であると想定しているとします。したがって、スペースを節約するには(たとえば、クライアント側の配列などで)、uint32_t(または単にint)を使用します。しかし、安全のために、データベースは、20年後に一部のユーザーが大量のIDなどを挿入したい場合に備えて、システムが明確に定義された優雅で目立つ方法で失敗するように(たとえば、違反する挿入を拒否する)、その制限を適用する必要があります。
データベースシステム
理想的には、ソリューションはデータベース間で移植可能である必要があります(結局のところ、SQLは国際標準です)-しかし、Oracle/Postgres固有の回答も有益です-1つのデータベースシステムでそれを行う方法を知っている場合は、多くの場合、もう一方のドキュメントで抽象的な概念を検索します。
タイプとトリガー
タイプのみのソリューションである必要はありません。トリガーは、制約を適用する他のメカニズムでもあります。タイプを使用するのが便利な方法だと想像しました。
制約によるSQLデータ型のドメインの単純な制限は、最も自然な方法です。 2つのオプションがあります
最初のオプションの例は次のようになります
ALTER TABLE table_name
ADD CONSTRAINT constraint_name
CHECK (column_name > -128 AND column_name < 127);
(必要に応じてテーブル、制約、列名を変更し、チェックされた境界の範囲を調整します)
2番目のオプションは2段階のプロセスです。まず、コマンドを使用して新しいドメインをDBに追加します(この例では、ドメインタイプの名前はc_byte8です)。
CREATE DOMAIN c_byte8 NUMERIC CONSTRAINT c_byte8_constraint
CHECK (VALUE > -128 AND VALUE < 127);
次に、適切なタイプでテーブルを作成します。属性のタイプとしてNUMERICの代わりにc_byte8。例えば。
CREATE TABLE test_table_1 (id NUMERIC, byte_value c_byte8);
最初の解決策では、定義した各属性に制約を追加する必要があることに注意してください。そうしないと、将来定義することになります。制限されたドメインを使用するたびに同じ制約条件が繰り返されるため、DB作成スクリプトが読みにくくなります。このアプローチの2つ目の欠点は、既存のスキーマにこれらの制約を追加すると、スキーマの一部の列を簡単に見逃してしまう可能性があることです。
最初のソリューションの利点は、既存のスキーマをそれほど面倒なく拡張できることです。
2番目のアプローチに関しては、実行中の本番DBのテーブル定義と同じように、プラスはより読みやすいDB作成スクリプトですが、既存の本番DBの変更はより複雑です。
データ型の選択によってこれを制限できるとは思いません。
ただし、プログラミング言語で表現できない値が挿入されないようにするチェック制約を作成できます。
alter table foo
add constraint check_type_range check (int_column < 32767);
実際の値を、選択したデータ型に一致する値に置き換える必要があります(Cは実行しないため、これらの制限が何であるかはわかりません)。
ビルド中に必要な情報を調べて、その結果を実装言語のデータ型にマッピングしたいと思います。たとえば、必要な情報を PostgreSQLのinformation_schemaビュー から検索できます。
select column_name, data_type, numeric_precision, numeric_precision_radix, numeric_scale
from information_schema.columns
where table_catalog = 'sandbox'
and table_schema = 'public'
and table_name = 'payors'
and column_name = 'payor_id'
column_name data_type numeric_precision numeric_precision_radix numeric_scale
--
payor_id integer 32 2 0