Foreign Key Check¶
Check name: foreign-key-check · Type: aggregate (integrity) · Config: ForeignKeyCheckConfig
Validates referential integrity: every value in a source column must exist in a column of a reference dataset. Use it to enforce foreign-key relationships between a fact table and its dimensions.
Parameters¶
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
check_id |
str |
yes | — | Unique identifier for this check within the CheckSet. |
column |
str |
yes | — | The source column to validate. |
reference_dataset |
str |
yes | — | Name of the reference dataset. YAML key: reference-dataset. |
reference_column |
str |
yes | — | The column in the reference dataset holding valid values. YAML key: reference-column. |
severity |
Severity |
no | CRITICAL |
CRITICAL fails the whole batch; WARNING only reports. |
Usage¶
Behavior¶
- Reference datasets are passed to
run_batch. The named dataset must be supplied viarun_batch(df, reference_datasets={"customers": customers_df}); the name must matchreference_dataset. A missing name raisesMissingReferenceDatasetError. - Dataset-level verdict. The check fails if any source value cannot be
resolved. Because it is a
CRITICALaggregate by default, a failure marks every row_dq_passed = False— including rows whose own key was valid. - Result and metrics. Available via
result.aggregate_results; themetricsdict reportsmissing_foreign_keys,total_rows, andmissing_ratio.
Example¶
Validating customer_id against a customers reference, where one value is
unresolved.
from pyspark.sql import SparkSession
from sparkdq.checks import ForeignKeyCheckConfig
from sparkdq.engine import BatchDQEngine
from sparkdq.management import CheckSet
spark = SparkSession.builder.getOrCreate()
orders = spark.createDataFrame([
{"id": 1, "customer_id": 10},
{"id": 2, "customer_id": 99},
])
customers = spark.createDataFrame([{"cid": 10}, {"cid": 20}])
check_set = CheckSet().add_check(
ForeignKeyCheckConfig(
check_id="customer-resolvable",
column="customer_id",
reference_dataset="customers",
reference_column="cid",
)
)
result = BatchDQEngine(check_set).run_batch(
orders, reference_datasets={"customers": customers}
)
for r in result.aggregate_results:
print(r.check_id, r.passed, r.metrics)
import yaml
from pyspark.sql import SparkSession
from sparkdq.engine import BatchDQEngine
from sparkdq.management import CheckSet
spark = SparkSession.builder.getOrCreate()
orders = spark.createDataFrame([
{"id": 1, "customer_id": 10},
{"id": 2, "customer_id": 99},
])
customers = spark.createDataFrame([{"cid": 10}, {"cid": 20}])
with open("checks.yml") as f:
config = yaml.safe_load(f)
check_set = CheckSet()
check_set.add_checks_from_dicts(config)
result = BatchDQEngine(check_set).run_batch(
orders, reference_datasets={"customers": customers}
)
for r in result.aggregate_results:
print(r.check_id, r.passed, r.metrics)
The aggregate result reports the unresolved count and ratio:
Typical use cases¶
- Ensure every
order.customer_idresolves to a known customer. - Validate fact-table foreign keys against dimension tables.
- Enforce referential integrity across datasets in a lake or warehouse.
Related checks¶
- Is Contained In Check — restrict values to a static in-config set rather than a reference dataset.