Expectations in Lakeflow Declarative Pipelines (formerly Delta Live Tables / DLT) are a declarative way to validate and control data quality inside a pipeline. You embed rules like "this column must not be NULL" or "amount must be non-negative" directly in the table definition, and choose whether violating records are logged, dropped, or whether the entire pipeline should fail.
This article walks through the 3 operating modes of Expectations, both SQL and PySpark syntax, the quarantine pattern, quality monitoring via the event log, and how Expectations compare to Delta Table Constraints (NOT NULL / CHECK).
Expectations come in 3 modes that differ in how violating records are handled. You pick a mode based on the nature of the pipeline (batch vs. streaming) and business requirements (how much data loss is acceptable).
| Mode | Behavior on violation | Effect on output table | Pipeline continues? | Typical use case |
|---|---|---|---|---|
| EXPECT (log) | Records violations but still writes them to output | All records written | Continues | Quality monitoring, early-stage visibility |
| EXPECT OR DROP (drop) | Excludes violating records from output | Only passing records written | Continues | Filtering bad data, building Silver tables |
| EXPECT OR FAIL (fail) | A single violation stops the pipeline | Transaction is rolled back | Stops | Gold tables, billing data, anything that cannot tolerate gaps |
EXPECT mode is the right choice when you do not want to stop the pipeline on violations but still want to track their count. A typical use case is initial Bronze-layer ingestion, where you monitor violation trends via the event log.
To define Expectations in SQL, you use the CONSTRAINT clause inside a CREATE OR REFRESH statement. Quality rules are declared inline as part of the table definition.
-- EXPECT: 違反を記録するが全レコードを出力に含める
CREATE OR REFRESH MATERIALIZED VIEW silver_orders
(
CONSTRAINT valid_amount EXPECT (amount > 0),
CONSTRAINT not_null_id EXPECT (order_id IS NOT NULL)
)
AS SELECT * FROM LIVE.bronze_orders;
-- EXPECT OR DROP: 違反レコードを出力から除外
CREATE OR REFRESH MATERIALIZED VIEW silver_orders_clean
(
CONSTRAINT valid_amount EXPECT (amount > 0) ON VIOLATION DROP ROW,
CONSTRAINT not_null_id EXPECT (order_id IS NOT NULL) ON VIOLATION DROP ROW
)
AS SELECT * FROM LIVE.bronze_orders;
-- EXPECT OR FAIL: 1件でも違反があればパイプラインを停止
CREATE OR REFRESH MATERIALIZED VIEW gold_revenue
(
CONSTRAINT valid_amount EXPECT (amount > 0) ON VIOLATION FAIL UPDATE
)
AS SELECT region, SUM(amount) AS total FROM LIVE.silver_orders_clean
GROUP BY region;CONSTRAINT names must be unique within the pipeline. Since the event log uses these names as the key for tracking violation counts, business-meaningful names like valid_amount or not_null_customer_id are recommended.
In PySpark, Expectations are defined via decorators. In practice, the @dlt.expect_all family is most commonly used because it accepts multiple rules as a dictionary.
import dlt
from pyspark.sql.functions import col
# 単一条件の EXPECT(記録のみ)
@dlt.table
@dlt.expect("valid_amount", "amount > 0")
@dlt.expect("not_null_id", "order_id IS NOT NULL")
def silver_orders():
return dlt.read_stream("bronze_orders")
# 複数条件をまとめて DROP
quality_rules = {
"valid_amount": "amount > 0",
"not_null_id": "order_id IS NOT NULL",
"valid_region": "region IN ('APAC','EMEA','NA')"
}
@dlt.table
@dlt.expect_all_or_drop(quality_rules)
def silver_orders_clean():
return dlt.read_stream("bronze_orders")
# FAIL: 1件でも違反でパイプライン停止
@dlt.table
@dlt.expect_all_or_fail({"positive_revenue": "total > 0"})
def gold_revenue():
return (
dlt.read("silver_orders_clean")
.groupBy("region")
.agg({"amount": "sum"})
.withColumnRenamed("sum(amount)", "total")
)@dlt.expect_all takes a dictionary and applies every rule in EXPECT (log) mode. @dlt.expect_all_or_drop and @dlt.expect_all_or_fail correspond to DROP and FAIL modes respectively. Extracting the dictionary into an external variable makes rule management and test-time substitution much easier.
EXPECT OR DROP makes records disappear, and EXPECT lets bad data flow downstream. When you want to keep violating data but prevent it from reaching downstream tables, use the quarantine table pattern.
import dlt
from pyspark.sql.functions import expr
@dlt.table(comment="品質条件を満たすレコードのみ")
def silver_orders_valid():
return (
dlt.read_stream("bronze_orders")
.filter("amount > 0 AND order_id IS NOT NULL")
)
@dlt.table(comment="品質違反レコードを隔離")
def silver_orders_quarantine():
return (
dlt.read_stream("bronze_orders")
.filter("amount <= 0 OR order_id IS NULL")
.withColumn("quarantine_reason",
expr("""CASE
WHEN amount <= 0 THEN 'invalid_amount'
WHEN order_id IS NULL THEN 'null_order_id'
ELSE 'unknown'
END"""))
)Adding a violation-reason column to the quarantine table makes it useful for data quality reporting, root-cause analysis by ops teams, and reinjection workflows after the data is fixed.
Expectations violation counts are recorded automatically in the pipeline event log. You can see them on the pipeline detail page in the UI, or query the event_log table directly with SQL.
SELECT
details:flow_progress.data_quality.expectations.name AS expectation_name,
details:flow_progress.data_quality.expectations.dataset AS dataset,
details:flow_progress.data_quality.expectations.passed_records AS passed,
details:flow_progress.data_quality.expectations.failed_records AS failed,
timestamp
FROM event_log(TABLE(my_catalog.my_schema.my_pipeline))
WHERE event_type = 'flow_progress'
AND details:flow_progress.data_quality IS NOT NULL
ORDER BY timestamp DESC;This query returns the pass and fail counts for each Expectation over time. Combine it with alerting on sudden spikes in violation rates to catch upstream data-quality regressions early.
DLT Expectations and Delta Table Constraints both relate to data quality, but they operate at different layers and behave differently.
| Aspect | DLT Expectations | Delta Constraints (NOT NULL / CHECK) |
|---|---|---|
| Where it applies | In-pipeline data flow inside DLT | At write time to a Delta table |
| How it's defined | CONSTRAINT clause / @dlt.expect decorator | ALTER TABLE ADD CONSTRAINT |
| Violation options | Three modes: log, drop, fail | Write error (rejection) only |
| Metrics capture | Automatically recorded in the event log | None (error logs only) |
| Usable outside DLT? | No (DLT pipelines only) | Yes (applies to ordinary Spark writes too) |
| Typical purpose | Monitoring and filtering quality at intermediate pipeline stages | Schema guard on the final table |
In practice, the robust pattern is to use DLT Expectations to check quality progressively through the pipeline, then place Delta Constraints on the final Gold table so that only data that has cleared every quality check can be written.
This staged quality gating minimizes the risk of upstream quality issues propagating downstream, while preventing data loss at the Bronze layer.
Data Engineer Associate / Professional
問題 1
On a DLT pipeline Silver table, you want to exclude records where amount <= 0 from the output and track the violation count in the event log. The pipeline must not stop on violations. Which is the most appropriate approach?
正解: B
EXPECT ... ON VIOLATION DROP ROW excludes violating records from the output while letting the pipeline continue, and the violation count is recorded in the event log. EXPECT alone (A) still writes every record to the output. FAIL UPDATE (C) stops the pipeline. The CHECK constraint (D) is a Delta table constraint, not a DLT pipeline feature, and does not emit quality metrics to the event log.
Where do records dropped by EXPECT OR DROP go? Can they be recovered?
Records dropped by EXPECT OR DROP are not written to the output table and are not automatically retained by default. Only the dropped-row count is captured in the event log. To make them recoverable, you need to implement a quarantine pattern yourself by routing violating records to a separate table.
Where can I see Expectations violation metrics?
They are recorded in the DLT pipeline event log (event_log). The flow_progress.data_quality.expectations field exposes the name, passed count, and failed count for each Expectation. You can also see them as charts on the pipeline detail page in the UI.
Can I combine Expectations with Delta Constraints?
Yes, they work well together. Expectations validate quality during the in-pipeline data flow, while Delta Constraints (NOT NULL / CHECK) enforce rules at table write time. A robust design uses Expectations for soft monitoring and Delta Constraints on the final table as a hard guard.
Practice with certification-focused question sets
無料で問題を解いてみるNicheeLab Editorial Team
NicheeLab editorial team focused on data engineering and cloud certification learning. Content is structured around practical study needs and official exam domains.
Databricks Certifications: All 7 Exams, Difficulty & Study Plan (2026)
Complete guide to all 7 Databricks certifications — Data Eng...
Databricks Exam Difficulty Ranking: All 7 Certs Compared (2026)
Every Databricks certification ranked by difficulty, with st...
Databricks Study Guide: Fastest Pass Route & Time Estimates (2026)
How to pass Databricks certifications efficiently. Official ...
Databricks Data Engineer Associate: Complete Guide (2026)
Domain-by-domain breakdown of the Databricks Certified Data ...
Databricks Data Engineer Professional: Complete Guide (2026)
Tactics for the Databricks Certified Data Engineer Professio...