Databricks DE ยท Topic 4.2
A SQL command that batch-loads files into a Delta table and skips files it already loaded โ idempotent, incremental, no streaming setup. This deep dive walks each capability with the code.
โธ run COPY INTO repeatedly; already-loaded files are skipped
COPY INTO tracks loaded files per target table and skips them on re-run โ even if the file was later modified (tracked by path, not content). FORMAT_OPTIONS = parsing; COPY_OPTIONS = load behavior.
COPY INTO cat.sch.bronze_sales FROM '/Volumes/cat/sch/vol/sales/' FILEFORMAT = CSV FORMAT_OPTIONS ('header' = 'true', 'inferSchema' = 'true') -- parsing COPY_OPTIONS ('mergeSchema' = 'true'); -- load behavior
PySpark โ COPY INTO is SQL, run via spark.sql
spark.sql("""COPY INTO cat.sch.bronze_sales
FROM '/Volumes/cat/sch/vol/sales/' FILEFORMAT = CSV
FORMAT_OPTIONS ('header' = 'true')""")
Wrap a SELECT to cast / rename / derive columns during ingestion โ type raw strings without a second pass.
COPY INTO cat.sch.bronze_sales FROM ( SELECT CAST(order_id AS BIGINT) AS order_id, CAST(amount AS DECIMAL(10,2)) AS amount, to_date(order_date, 'yyyy-MM-dd') AS order_date FROM '/Volumes/cat/sch/vol/sales/' ) FILEFORMAT = CSV FORMAT_OPTIONS ('header' = 'true');
-- PATTERN and FILES are mutually exclusive; FILES caps at 1000 COPY INTO cat.sch.bronze_sales FROM '/Volumes/cat/sch/vol/sales/' FILEFORMAT = CSV PATTERN = '2026-*.csv'; -- glob filter -- Test parsing/schema/constraints WITHOUT writing COPY INTO cat.sch.bronze_sales FROM '/Volumes/cat/sch/vol/sales/' FILEFORMAT = CSV VALIDATE 50 ROWS; -- or VALIDATE ALL
COPY INTO cat.sch.bronze_sales FROM '/Volumes/cat/sch/vol/sales/' FILEFORMAT = CSV COPY_OPTIONS ('force' = 'true', -- disable idempotency: reload everything 'mergeSchema' = 'true'); -- evolve new columns in
force=true is how you re-ingest after a fix (a modified same-path file is otherwise skipped). mergeSchema=true handles schema drift.cloudFiles streaming source, checkpointed.
availableNow| COPY INTO | Auto Loader | |
|---|---|---|
| Interface | SQL command | Structured Streaming |
| Scale | Thousands of files | Millions+ |
| State | Tracks loaded files | Checkpoint (RocksDB) |
| Best for | Simple periodic loads | Large-scale continuous |
COPY INTO bronze_sales FROM '...' loads each new day's file exactly once โ no checkpoint plumbing, just SQL in a job.SELECT.force); schema drift needs mergeSchema.force=true to override).force.mergeSchema when the incoming schema changes โ load errors.