Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 18

Incremental Data Loading with COPY INTO

Recommended resources

Hello! Welcome to the next lesson in our module on Incremental Data Ingestion.

In our last session, we delved into Auto Loader, exploring its powerful streaming capabilities and comparing its directory listing and file notification modes. You learned that Auto Loader is the premier tool for continuous, scalable file ingestion.

Today, we'll introduce another essential tool in your Databricks ingestion toolkit: the COPY INTO command. While Auto Loader excels at streaming, COPY INTO is designed for simple, idempotent, and incremental batch loading using SQL. As a data engineer with a strong SQL background, you'll find this command to be an intuitive and powerful way to handle many common ingestion tasks.

This lesson directly addresses the learning outcome: Use COPY INTO to load data incrementally into Delta tables. By the end, you'll understand its syntax, core features, and how to apply it in practical scenarios.

1. What is COPY INTO?

COPY INTO is a SQL command that efficiently loads data from a file location in cloud storage into a Delta table. It is best used when you need to perform batch ingestion, perhaps as part of a scheduled job, and prefer to work within a SQL-native environment.

Let's start with a brief overview from Databricks.

Data Ingestion using COPY INTO

This short video introduces COPY INTO and its primary use case: batch file ingestion for smaller file counts where a SQL approach is preferred.

Watch the following two short clips: 01:33 - 02:03: This part introduces the command and its ideal use case. 04:22 - 04:53: This section summarizes the key benefits, such as simplicity and efficiency for ingesting up to thousands of files.

The three most important characteristics of COPY INTO are:

  • Idempotent: This is a crucial feature. COPY INTO tracks which files have already been processed and will not load them again, even if you re-run the command. This ensures exactly-once processing at the file level, preventing data duplication.
  • Incremental: When you execute the command, it automatically discovers and processes only the new files that have arrived in the source directory since the last run.
  • SQL-native: It's a straightforward SQL command, making it easy to integrate into SQL-heavy workflows and Databricks SQL queries.

2. A Practical Walkthrough of COPY INTO

The best way to understand COPY INTO is to see it in action. We'll follow a detailed video that walks through a complete example, from setting up the environment to demonstrating its core features.

23 Databricks COPY INTO command | COPY INTO Metadata | Idempotent Pipeline | Exactly Once processing

This video from 'Ease With Data' provides an excellent, step-by-step demonstration of using COPY INTO. We will use it as our guide for this section.

We will break this video down section by section. For now, watch from the beginning to 01:18 to get an introduction to the command's benefits, such as being retriable and idempotent.

Step 1: Setting up the Source Data and Target Table

Before you can copy data, you need a source and a destination. A common pattern is:

  1. Land raw files (e.g., CSV, JSON) in a specific cloud storage location.
  2. Create an empty "placeholder" Delta table that will receive the data.

Unlike some other tools, COPY INTO requires the target Delta table to exist before you run the command. You can create it with a full schema, or, more flexibly, create it without any columns and let COPY INTO infer and evolve the schema for you.

Watch the next part of the video to see this setup process.

23 Databricks COPY INTO command | COPY INTO Metadata | Idempotent Pipeline | Exactly Once processing

Continuing with the 'Ease With Data' video, let's see how to prepare the environment.

Watch from 01:18 to 04:13. Observe how the presenter: Creates a volume and copies some source CSV files into it. Creates an empty placeholder Delta table (invoice_cp) with no schema defined.

Step 2: The COPY INTO Command Syntax

Now for the main event. The COPY INTO command has a clear structure. Let's look at the syntax and break down the key options.

COPY INTO my_bronze_table
FROM '/path/to/source/data'
FILEFORMAT = CSV
FORMAT_OPTIONS (
  'header' = 'true',
  'mergeSchema' = 'true'
)
COPY_OPTIONS (
  'mergeSchema' = 'true'
);

Let's dissect this with help from a practical guide.

Building Bronze Layer: Using COPY INTO in Databricks

This article provides a fantastic, clear breakdown of the command and its options.

Read the sections 'Command Breakdown' and 'Resolving the Initial Error'. Pay close attention to the explanation of FILEFORMAT, FORMAT_OPTIONS, and COPY_OPTIONS. Notice the distinction between the two mergeSchema options: FORMAT_OPTIONS ('mergeSchema'='true'): Merges the schemas of multiple source files before loading. COPY_OPTIONS ('mergeSchema'='true'): Allows the schema of the target Delta table to evolve if new columns are found.

Now, watch the demonstration of this command in the video.

23 Databricks COPY INTO command | COPY INTO Metadata | Idempotent Pipeline | Exactly Once processing

Let's see the basic COPY INTO command executed.

Watch from 04:13 to 07:15. The presenter writes the COPY INTO command and runs it. Notice the output, which shows the number of rows inserted.

Step 3: Verifying Idempotency and Incremental Loading

This is the magic of COPY INTO. What happens if you run the exact same command again?

23 Databricks COPY INTO command | COPY INTO Metadata | Idempotent Pipeline | Exactly Once processing

Let's continue the video to see idempotency in action.

Watch from 07:15 to 08:11. The presenter re-runs the command. Crucially, the output now shows '0' for the number of inserted rows. The data is not duplicated.

How does it work?
COPY INTO maintains metadata about the files it has already ingested within the Delta table's transaction log. Specifically, it creates a _copy_into_log directory. When the command runs, it first lists the files in the source directory and then filters out any files that are already recorded in this log.

The video gives a great look at this internal mechanism.

23 Databricks COPY INTO command | COPY INTO Metadata | Idempotent Pipeline | Exactly Once processing

Understanding the 'how' is key for a professional. This part of the video shows you where COPY INTO stores its state.

Watch from 08:11 to 09:38. You'll see the presenter inspect the table's underlying storage and point out the _delta_log/_copy_into_log directory, which is responsible for tracking processed files.

Now, let's confirm the incremental behavior. We'll add a new file to the source and re-run the command.

23 Databricks COPY INTO command | COPY INTO Metadata | Idempotent Pipeline | Exactly Once processing

The final test of the core functionality: loading new data incrementally.

Watch from 12:59 to 14:02. A new file is added to the source directory. When COPY INTO is run again, it correctly processes only the new file, ignoring the two that were already loaded.


3. Advanced Usage: Transformations During Ingestion

A powerful feature of COPY INTO is the ability to perform transformations as you load the data. You can embed a SELECT statement to choose specific columns, cast data types, or even add new columns, such as a load timestamp. This is highly useful for shaping data as it enters your bronze layer.

The syntax looks like this:

COPY INTO my_table
FROM (
  SELECT
    col_a,
    CAST(col_b AS INT),
    current_timestamp() AS load_ts
  FROM '/path/to/source/data'
)
FILEFORMAT = ...
...

Let's see a demonstration of this technique.

23 Databricks COPY INTO command | COPY INTO Metadata | Idempotent Pipeline | Exactly Once processing

This technique elevates COPY INTO from a simple loader to a light transformation tool. Let's watch how it's done.

Watch from 09:38 to 12:59. The presenter creates a new table with a predefined schema and then uses a SELECT query within the COPY INTO command to: Select only a subset of columns from the source file. Cast the quantity column to a double. Add a new insert_date column using current_timestamp().


4. Hands-On Practice

Now it's your turn. The best way to solidify your understanding is to run the commands yourself. The following Databricks tutorial provides a self-contained notebook that you can run in your workspace. It will guide you through setting up a data source, creating a target table, and using COPY INTO to load data idempotently.

Tutorial: COPY INTO with Spark SQL

Time to get your hands dirty. Please follow this official Databricks tutorial. It's a great exercise that reinforces everything we've covered.

Open a new Databricks notebook and follow the tutorial from 'Step 1' to 'Step 5'. Execute the code blocks in order. Pay special attention to what happens in 'Step 5' when you re-run the steps to simulate new data arriving—this will directly test your understanding of incremental and idempotent loading.


5. Key Insights and Best Practices

As you move towards production implementations, keep these professional-level insights in mind. They are critical for building robust and predictable pipelines with COPY INTO.

Building Bronze Layer: Using COPY INTO in Databricks

This article offers excellent advice based on real-world experience. Let's review the key takeaways.

Read the sections 'Key Insights and Best Practices' and 'Conclusion'. Focus on these two critical points: Idempotency is at the file level, not the record level. If a file with the same name is updated in the source, COPY INTO will not reprocess it. This makes file naming conventions very important. File name uniqueness matters. To avoid missing data updates, ensure each new batch of data arrives in a file with a unique name (e.g., by embedding a timestamp in the filename).


Conclusion

In this lesson, you have gained a comprehensive understanding of the COPY INTO command. It is a vital tool for any data engineer working in Databricks, especially for batch-oriented ingestion tasks.

Key Takeaways:

  • COPY INTO is a SQL command for incremental and idempotent batch loading of data into Delta tables.
  • It works by tracking processed file names in the Delta transaction log, which prevents data duplication.
  • It requires the target table to exist beforehand but can handle schema inference and evolution using FORMAT_OPTIONS and COPY_OPTIONS.
  • You can perform transformations on the fly by embedding a SELECT query within the command.
  • For robust production pipelines, always use unique file names for each new batch of data.

Preview of the Next Lesson:
You are now familiar with two powerful incremental ingestion tools: Auto Loader and COPY INTO. Each has its strengths. In our next lesson, we will compare Auto Loader vs. COPY INTO directly. You will learn how to analyze a scenario and select the most appropriate tool based on factors like data volume, velocity, latency requirements, and operational complexity.