メインコンテンツにスキップ
モジュール 9 · レッスン 2 / 4コース内の 34/57~12 min
モジュールのレッスン (2/4)

複数のテーブルレベルの制約

データベース内のデータが最も基本的な層 (「データの整合性」) で正しいことを確認することが基本です。 Node.js アプリケーションに安全性のみを書き込むと、バグにより DB 内のデータの不整合が発生する可能性があります。 DDL レベルの制約は、最後の突破不可能な防御線です。

主な制約

PRIMARY KEY (列を一意で NOT NULL にする) と従来の NOT NULL および UNIQUE に加えて、データの論理的一貫性には 2 つの基本的なカテゴリがあります。

1. FOREIGN KEY (参照整合性)

REFERENCES 制約は、リンク ID がそれが指す「親」テーブルに実際に存在することを保証します。 たとえば、注文は既存の顧客にリンクされている必要があります。

SQL
CREATE TABLE orders (
  id SERIAL PRIMARY KEY,
  customer_id INTEGER REFERENCES customers(id)
);

外部キーは何をしますか?

  • customers に存在しない customer_id を挿入できなくなります。
  • 顧客を指す注文がある場合、顧客を DELETE (削除) することができなくなります (「孤立」レコードから保護されます)。

「親」が削除されたときに何が起こるかを決定することもできます。

SQL
customer_id INTEGER REFERENCES customers(id) ON DELETE CASCADE

ON DELETE CASCADE では、顧客を削除すると、Postgres はリンクされているすべての orders を自動的に 削除します。 (使用には十分な注意が必要です。通常は、操作をブロックするデフォルト設定を使用することをお勧めします。)

2. 制約の確認

CHECK 制約は、保存に進む前にブール式をテストすることで行を検証します。

SQL
CREATE TABLE contratti (
  id SERIAL PRIMARY KEY,
  stipendio NUMERIC(10,2) CHECK (stipendio > 0),
  data_inizio DATE,
  data_fine DATE,
  CHECK (data_fine > data_inizio)
);

最初の CHECK は 列制約 (stipendio のみを参照します)。 一番下にある 2 番目の CHECK は テーブル制約 (複数の列の値を横断できるため、一番下で宣言する必要があります) です。

INSERT または UPDATE が開始前に終了を保存しようとすると、Postgres はエラーで拒否します。

命名上の制約

多くの場合、制約に明示的な名前を付けることをお勧めします (CONSTRAINT キーワードを使用)。こうすることで、Postgres がレコードをブロックすると、たとえば「制約 'stipendio_positivo' に違反しました」というエラーが表示され、デバッグがよりわかりやすくなります。

SQL
CREATE TABLE prodotti (
  id SERIAL PRIMARY KEY,
  nome VARCHAR(50),
  CONSTRAINT nome_univoco UNIQUE(nome)
);

試してみてください

運動#sql.m9.l2.e1
試行回数: 0読み込み中…

ID (SERIAL PRIMARY KEY) と 'customer_id' (INTEGER) を使用して 'prenotazioni' テーブルを作成します。 CONSTRAINT fk_cliente FOREIGN KEY (customer_id) REFERENCES Customers(id) を使用して、外部キー制約に明示的な名前を付けます。これをテーブル制約として一番下で実行します。

エディターを読み込み中…
ヒントを表示

書き込み CONSTRAINT fk_cliente FOREIGN KEY (local_column) REFERENCES external_table(external_col)

3 回の試行後に解決策が利用可能になります

カスタムロジックによる制約

運動#sql.m9.l2.e2
試行回数: 0読み込み中…

ID (SERIAL PRIMARY KEY)、posti_totali (INTEGER)、biglietti_venduti (INTEGER) を使用して「eventi」テーブルを作成します。 「check_capienza」という名前のテーブル制約を追加します。ここで、biglietti_venduti は posti_totali よりも大きくなってはなりません。

エディターを読み込み中…
ヒントを表示

CONSTRAINT check_capienza CHECK (expression) を使用して、下部に制約を追加します。

3 回の試行後に解決策が利用可能になります