實作資料型別檢查

已完成

您的資料集中的每一個欄位都有預期的資料型態,當輸入資料不符合預期時,問題會在後續過程中引發連鎖問題。 字串中包含整數可能會中斷計算、損壞聚合,或導致管線故障。 資料型別檢查確保每個欄位在輸入資料表前都包含正確類型的值。

在這個單元中,你會學習如何在 Azure Databricks 中利用結構強制、顯式型別轉換以及驗證限制來實作資料型別檢查。

了解結構描述強制執行

Delta Lake 在你寫入資料表時會自動驗證資料型別。 這種內建機制稱為 結構強制,會將輸入欄位的資料型態與目標資料表的架構進行比較。 當類型不匹配時,Delta Lake 嘗試安全地轉換該數值。 若鑄造失敗,寫入操作會產生錯誤。

在插入作業期間,結構描述強制執行會套用下列規則:

  • 所有插入的欄位必須存在於目標資料表中
  • 所有欄位資料型別必須與目標型別相符或可安全轉換

考慮一個整數欄位的表格:

CREATE TABLE inventory (
    product_id INT,
    quantity INT,
    last_updated DATE
);

當你插入代表 quantity 數字的字串資料時,Delta Lake 會將其投射成目標類型:

-- This succeeds because '100' can be cast to INT
INSERT INTO inventory VALUES (1, '100', '2026-01-15');

然而,插入無法轉換為整數的字串會導致操作失敗:

-- This fails because 'fifty' cannot be cast to INT
INSERT INTO inventory VALUES (2, 'fifty', '2026-01-15');

結構描述強制執行提供防範型別不相符的第一道防線。 若需要更精細地控制不相符的處理方式,您可以使用明確轉型。

使用明確型別轉型

這個 cast 函式會將值從一種資料型態轉換到另一種。 轉換失敗時會產生錯誤。 try_cast 函式同樣運作,但轉換失敗時會回傳 NULL 而非引發錯誤。

當你想要嚴格驗證並停止處理無效資料時,請使用 cast :

SELECT 
    cast(raw_amount AS DECIMAL(10,2)) AS amount,
    cast(raw_date AS DATE) AS transaction_date
FROM staging_data;

當你想辨識無效值而不失敗查詢時,請使用 try_cast :

SELECT 
    raw_amount,
    try_cast(raw_amount AS DECIMAL(10,2)) AS validated_amount,
    CASE 
        WHEN try_cast(raw_amount AS DECIMAL(10,2)) IS NULL 
        THEN 'Invalid amount format'
        ELSE 'Valid'
    END AS validation_status
FROM staging_data;

使用 try_cast,具有無效值的記錄在轉型的資料行中會傳回 NULL。 接著你可以根據資料品質需求,對這些紀錄進行過濾、標記或隔離。

實作帶有約束的型別驗證

CHECK 約束 允許你定義自訂的驗證規則,並在資料插入或更新時強制執行。 雖然通常用於值範圍與模式,但你可以將它們與型別感知函數結合,建立複雜的型別檢查。

例如,你可以驗證字串欄位是否僅包含數字字元:

CREATE TABLE orders (
    order_id INT,
    order_total STRING
);

ALTER TABLE orders
ADD CONSTRAINT valid_order_total CHECK (order_total REGEXP '^[0-9]+(\\.[0-9]+)?$')

此限制確保 order_total 欄位包含看似有效數字的值,並在資料進入資料表前捕捉其格式錯誤。

對於日期驗證,你可以在一個限制條件下使用 這個 try_cast 函式:

ALTER TABLE events 
ADD CONSTRAINT valid_event_date CHECK (try_cast(event_date_str AS DATE) IS NOT NULL);

此方法會拒絕不包含有效日期格式的紀錄 event_date_str 。

這很重要

在對現有資料表新增限制前,Azure Databricks 會先驗證所有現有資料列是否符合該限制。 針對大型表格,請務必規劃這個驗證步驟。

在管線中處理型別不相符

處理外部來源資料時,類型不匹配是常見的。 實作一套模式,將有效與無效紀錄區分開來,讓你能處理良好的資料,同時隔離有問題的紀錄以便審查:

-- Insert valid records into the target table
INSERT INTO silver_transactions
SELECT 
    transaction_id,
    cast(amount AS DECIMAL(10,2)) AS amount,
    cast(transaction_date AS DATE) AS transaction_date
FROM bronze_transactions
WHERE try_cast(amount AS DECIMAL(10,2)) IS NOT NULL
  AND try_cast(transaction_date AS DATE) IS NOT NULL;

-- Capture invalid records for investigation
INSERT INTO quarantine_transactions
SELECT 
    transaction_id,
    amount AS raw_amount,
    transaction_date AS raw_date,
    current_timestamp() AS quarantined_at,
    'Type validation failed' AS reason
FROM bronze_transactions
WHERE try_cast(amount AS DECIMAL(10,2)) IS NULL
   OR try_cast(transaction_date AS DATE) IS NULL;

此模式確保管線持續處理有效資料,同時保留無效紀錄以供後續分析。

使用管線預期進行型別檢查

Lakeflow 管線提供 預期條件,讓你能直接在管線定義中定義資料品質規則。 你可以利用期望來確認值可轉換至期望型別:

from pyspark import pipelines as dp

@dp.table
@dp.expect_or_drop("valid_amount", "try_cast(amount AS DECIMAL(10,2)) IS NOT NULL")
@dp.expect_or_drop("valid_date", "try_cast(event_date AS DATE) IS NOT NULL")
def validated_transactions():
    return spark.readStream.table("raw_transactions")

在 expect_or_drop中,未通過型別檢查的紀錄會在到達目標表前被丟棄。 用於 expect 記錄違規且不丟棄紀錄,或 expect_or_fail 在違規發生時停止管線。

針對基於 SQL 的管線:

CREATE OR REFRESH STREAMING TABLE validated_transactions (
    CONSTRAINT valid_amount EXPECT (try_cast(amount AS DECIMAL(10,2)) IS NOT NULL) ON VIOLATION DROP ROW,
    CONSTRAINT valid_date EXPECT (try_cast(event_date AS DATE) IS NOT NULL) ON VIOLATION DROP ROW
)
AS SELECT * FROM STREAM(raw_transactions);

管線期望將資料型別驗證直接整合進你的 ETL 邏輯,透過管線介面提供資料品質指標的可視化。

在多個層級實施資料型別檢查——架構強制執行、明確鑄造、約束條件及管線期望——能建立深度防禦。 每一層都能捕捉可能忽略的問題,從而提升 Unity 目錄資料表的資料品質。