Databricks の制約
Databricksは、標準的なSQL制約管理句をサポートしています。
- 強制された制約では、テーブルに行を追加する前にデータの完全性が検証されます。
- 情報制約(主キー、外部キー、および一意制約)は、テーブル内のフィールド間のリレーションシップを定義しますが、強制されません。
Databricks のすべての制約には Delta Lake が必要です。
For a related concept in LakeFlow Pipelines, see 「パイプラインの期待値を使用してデータ品質を管理」。
適用される制約
制約に違反した場合、トランザクションはエラーで失敗します。Databricksは2種類の制約をサポートしています。
NOT NULL: 特定の列の値を null にできないことを示します。CHECK: 指定されたブール式が各入力行に対して true である必要があることを示します。
制約を追加すると、現在のライターバージョンが 3 未満の場合にテーブルライタープロトコルがアップグレードされます。これは、外部の Delta Lake クライアントとの互換性に影響を与える可能性があります。Delta Lake 機能の互換性とプロトコルを参照してください。
NOT NULL制約
テーブルを作成するときは、スキーマ内で NOT NULL 制約を指定します。作成後に NOT NULL 制約を削除または追加するには、ALTER TABLE ... ALTER COLUMN コマンドを使用します。次の例では、このセクションの残りの部分で再利用する people_demo テーブルを作成します:
CREATE OR REPLACE TABLE main.default.people_demo (
id INT NOT NULL,
firstName STRING,
middleName STRING NOT NULL,
lastName STRING,
gender STRING,
birthDate TIMESTAMP,
ssn STRING,
salary INT
);
ALTER TABLE main.default.people_demo ALTER COLUMN middleName DROP NOT NULL;
ALTER TABLE main.default.people_demo ALTER COLUMN ssn SET NOT NULL;
Databricksは、テーブルにNOT NULL制約を追加する前に、既存のすべての行が制約を満たしていることを確認します。
構造体内にネストされた列にNOT NULL制約を指定する場合、親構造体もnullであってはなりません。配列型またはマップ型の中にネストされた列は、 NOT NULL制約を受け入れません。
CREATE TABLE [USING]とALTER TABLE ALTER COLUMNを参照してください。
CHECK制約
CHECK制約はALTER TABLE ADD CONSTRAINTコマンドとALTER TABLE DROP CONSTRAINTコマンドで管理します。ALTER TABLE ADD CONSTRAINT 、テーブルに制約を追加する前に、既存のすべての行が制約を満たしていることを確認します。
チェック制約には以下の制限が適用されます。
CHECK制約式では、以下の種類の関数を除き、同じ引数値が与えられた場合に常に同じ結果を返すSparkのSQL関数を使用できます。- ユーザー定義関数
- 集計関数
- ウィンドウ関数
- 複数の行を返す関数
既存のテーブルに追加する
次の例では、前のセクションで作成した people_demo テーブルに CHECK 制約を追加し、その後それを削除します:
ALTER TABLE main.default.people_demo ADD CONSTRAINT dateWithinRange CHECK (birthDate > '1900-01-01');
ALTER TABLE main.default.people_demo DROP CONSTRAINT dateWithinRange;
ALTER TABLE ADD CONSTRAINTとALTER TABLE DROP CONSTRAINTを参照してください。
チェック制約テーブルのプロパティを表示する
テーブルの CHECK 制約を確認するには、DESCRIBE DETAIL および SHOW TBLPROPERTIES コマンドを使用します。次の例では、people_demo に制約を追加してから表示します:
ALTER TABLE main.default.people_demo ADD CONSTRAINT validIds CHECK (id > 1 and id < 99999999);
DESCRIBE DETAIL main.default.people_demo;
SHOW TBLPROPERTIES main.default.people_demo;
チェック制約を削除する
Databricks Runtime 15.4 LTS以降では、 DROP FEATUREコマンドを使用してテーブルからチェック制約を削除し、テーブルプロトコルをダウングレードします。
Delta Lake テーブル機能の削除およびテーブル プロトコルのダウングレードを参照してください。
主キー、外部キー、および一意性制約を宣言する
主キー、外部キー、および一意制約は情報提供のみを目的としており、強制されません。クエリの最適化により、パフォーマンスが向上する可能性があります。
- **プライマリキーと外部キー**: Databricks Runtime 13.3 LTS 以降の Unity Catalog および Delta Lake テーブルで利用可能です。Databricks Runtime 15.2 以降で一般提供されます。外部キーは、別のテーブル内のプライマリキーまたは一意制約を参照する必要があります。
- Unique : Databricks SQL および Databricks Runtime 18.2 以降の Unity Catalog および Delta Lake テーブルでパブリックプレビューとして利用可能です。テーブルは複数の「一意制約」を持つことができます。外部キーは、
REFERENCES parent_table(unique_col)を使用して一意の列を参照できます。一意の列は NULL 可能にできます。これは、NULLの値が互いに異なるものとして扱われるためです。
information_schemaをクエリするか、DESCRIBE TABLE EXTENDEDまたはSHOW CREATE TABLEを使用して、特定のカタログにわたる制約の適用方法の詳細を取得します。
新しいテーブルに追加
テーブル作成時におけるテーブル仕様句の一部として、主キー、外部キー、および一意制約を宣言する
CREATE OR REPLACE TABLE main.default.T(pk1 INTEGER NOT NULL, pk2 INTEGER NOT NULL,
CONSTRAINT t_pk PRIMARY KEY(pk1, pk2));
CREATE OR REPLACE TABLE main.default.S(pk INTEGER NOT NULL PRIMARY KEY,
fk1 INTEGER, fk2 INTEGER,
CONSTRAINT s_t_fk FOREIGN KEY(fk1, fk2) REFERENCES main.default.T);
CREATE OR REPLACE TABLE main.default.U(id INTEGER NOT NULL, email STRING NOT NULL,
CONSTRAINT u_uq_email UNIQUE(email));
CTASステートメントはこの制約句をサポートしていません。
既存のテーブルに追加する
あるいは、既に存在するテーブルに同じ制約を追加します。このアプローチでも、前のセクションと同じ結果が得られます。次の例では、制約なしで T、S、および U を再作成し、その後 ALTER TABLE ADD CONSTRAINT を使用して各制約を追加します。それを参照する外部キーの前に主キーを追加します:
CREATE OR REPLACE TABLE main.default.T(pk1 INTEGER NOT NULL, pk2 INTEGER NOT NULL);
CREATE OR REPLACE TABLE main.default.S(pk INTEGER NOT NULL, fk1 INTEGER, fk2 INTEGER);
CREATE OR REPLACE TABLE main.default.U(id INTEGER NOT NULL, email STRING NOT NULL);
ALTER TABLE main.default.T ADD CONSTRAINT t_pk PRIMARY KEY(pk1, pk2);
ALTER TABLE main.default.S ADD CONSTRAINT s_t_fk FOREIGN KEY(fk1, fk2) REFERENCES main.default.T;
ALTER TABLE main.default.U ADD CONSTRAINT u_uq_email UNIQUE(email);