Loading...

We've detected that your browser language is Chinese. Would you like to visit our Chinese website? [ Dismiss ]
By: Emma

The PostgreSQL COPY command is a high-performance utility for transferring data between database tables and files. Compared with individual INSERT statements, it significantly speeds up bulk imports and exports, making it a common choice for data migration, backups, and reporting.

This guide covers PostgreSQL COPY command syntax, practical examples for importing and exporting data, the differences between COPY and \copy, and solutions to common errors.

What Is the COPY Command in PostgreSQL?

The PostgreSQL COPY command is a high-performance utility for transferring large volumes of data between database tables and files or streams. Unlike standard INSERT statements, it is designed for bulk data operations and significantly reduces the overhead of processing rows one at a time.

COPY moves structured data directly between a PostgreSQL table and a file on the server file system or an active client stream. By minimizing query parsing and network overhead, it can import or export millions of rows much faster than executing individual INSERT statements.

The direction of the data transfer depends on the option you use:

  • COPY ... FROM imports data from an external file into an existing PostgreSQL table. The target table must already exist because COPY does not create tables.
  • COPY ... TO exports data from a PostgreSQL table or the results of a SQL query to an external file. It is commonly used to create CSV files, generate reports, or back up table data.

what is posegresql copy command

PostgreSQL COPY Command Syntax

Before importing or exporting data, it is important to understand the basic PostgreSQL COPY command syntax and the available options. Knowing how these components work helps prevent formatting errors and ensures successful data transfers.

Basic Syntax

Use the following syntax to import data from a file into an existing PostgreSQL table:

sql
COPY table_name (column1, column2, column3)
    FROM '/path/to/file.csv'
    [WITH (option [, ...])];    

To export data from a table to a file, replace FROM with TO:

sql
COPY table_name (column1, column2, column3)
    TO '/path/to/file.csv'
    [WITH (option [, ...])];    

The column list is optional. If you omit it, PostgreSQL maps the file data to every column in the target table using the table’s default column order.

Common COPY Options

You can control how PostgreSQL imports or exports data by specifying options in the WITH clause.

  • FORMAT: Specifies the file format. Supported values are text, csv, and binary. The default is text.
  • HEADER: Indicates that the file contains a header row. During import, PostgreSQL skips the first row. During export, it writes the column names as the first row. This option is available only with the csv format.
  • DELIMITER: Defines the character used to separate columns. The default delimiter is a tab for text format and a comma for csv format.
  • NULL: Specifies the string that represents a NULL value. The default is \N for text format and an unquoted empty string for csv format.
  • QUOTE: Specifies the quotation character used for fields containing delimiters. The default is the double quotation mark (“). This option applies only to the csv format.
  • ESCAPE: Specifies the character used to escape special characters, including the quotation character. By default, PostgreSQL uses the same character defined for QUOTE.
  • ENCODING: Specifies the character encoding of the input or output file, such as UTF8 or LATIN1. PostgreSQL automatically converts the data if the file encoding differs from the database encoding.

How to Use COPY to Export and Import Data

Transferring data between database tables and local files is one of the most frequent administrative tasks in database management. Below are practical examples for both directions.

How to Export Data Using COPY

Exporting with COPY allows you to write table data or query results to a file. Exporting to CSV is one of the most common use cases, since most spreadsheet tools and data pipelines accept this format directly.

Export an Entire Table to CSV

To dump all rows from a table into a CSV file with headers, use the TO clause and specify the csv format.

sql
COPY employees TO '/tmp/employees.csv' WITH (FORMAT csv, HEADER);

Export Query Results

You can also export only a subset of data by passing a query inside parentheses.

sql
COPY (SELECT id, name, department FROM employees WHERE salary > 50000) TO '/tmp/high_earners.csv' WITH (FORMAT csv, HEADER);

Export Selected Columns

If you only need a few specific fields from a table, list them in parentheses after the table name.

sql
COPY employees (id, email) TO '/tmp/emails.csv' WITH (FORMAT csv, HEADER);

Export Without Headers

To export data without a header row, simply omit the HEADER option from your configuration parameters.

sql
COPY employees TO '/tmp/employees_no_header.csv' WITH (FORMAT csv);

How to Import Data Using COPY

Unlike client-side tools, COPY requires the source file to sit on the same machine as the PostgreSQL server, since the command runs server-side. The target table layout should align with the incoming file structure.

Import a CSV File into a Table

To load a standard comma-separated file that contains a header row, use the FROM keyword and enable the header option.

sql
COPY employees FROM '/tmp/employees.csv' WITH (FORMAT csv, HEADER);

Import Specific Columns

If the source CSV has fewer fields than the destination table, map the target columns explicitly so the engine matches the data correctly.

sql
COPY employees (name, department, salary) FROM '/tmp/new_hires.csv' WITH (FORMAT csv, HEADER);

Handling NULL Values

If your source file represents missing data with a specific word or phrase, define that value using the NULL option.

sql
COPY employees FROM '/tmp/employees_nulls.csv' WITH (FORMAT csv, HEADER, NULL 'N/A');

Import Files with Different Delimiters

When dealing with non-standard files, like those separated by semicolons instead of commas, adjust the DELIMITER parameter.

sql
COPY employees FROM '/tmp/employees_semicolon.csv' WITH (FORMAT csv, HEADER, DELIMITER ';');

COPY vs \copy: Which One Should You Use?

Although COPY and \copy perform similar tasks, they work in different environments. Understanding the difference between server-side and client-side execution helps you choose the right command and avoid common file access errors.

The SQL COPY command runs on the PostgreSQL server, which means the server reads from or writes to files on its own file system. To use COPY with server files, your database account typically requires superuser privileges or roles such as pg_read_server_files or pg_write_server_files.

By contrast, \copy is a meta-command provided by the psql client. It reads from or writes to files on your local machine, then streams the data to or from the PostgreSQL server. Because file access is handled by the client, \copy usually works without elevated server-side privileges.

The table below summarizes the key differences between the two commands.

Feature COPY \copy
Where it runs On the PostgreSQL server In the local psql client
File location Server file system Local file system
Permission requirements Superuser or server file roles Standard database user permissions
Best use cases Server‑side imports, exports, and automated data transfers Local development, remote databases, and environments with limited server access

Tip: If you receive a “could not open file” error, check where your file is located. COPY reads files from the database server, while \copy reads files from your local machine.

PostgreSQL COPY Command Examples for Everyday Tasks

These COPY command examples cover common day-to-day scenarios that database administrators and developers run into regularly.

Backup a Table to CSV

Creating a quick backup of a specific table is a useful step before running risky update statements. This example saves the customers table to a temporary directory on the server with headers included.

sql
COPY customers TO '/tmp/customers_backup.csv' WITH (FORMAT csv, HEADER);

Restore Data from CSV

When restoring a table from a previously exported file, truncating the target table first helps avoid duplicate primary key violations. Use matching options from your original export operation to read the file correctly.

TRUNCATE TABLE customers;

sql
TRUNCATE TABLE customers;
    COPY customers FROM '/tmp/customers_backup.csv' WITH (FORMAT csv, HEADER);    

Move Data Between PostgreSQL Databases

You can pipe data from one database directly into another using the command line with psql and client-side streaming. This approach avoids writing any intermediate files to disk, saving space and time. If the two databases are on different servers, add the -h flag to specify each host.

shell
psql -d source_db -c "\copy orders TO STDOUT" | psql -d target_db -c "\copy orders FROM STDIN"

Generate Reports from SQL Queries

Instead of exporting entire tables, database reporting often needs filtered data. You can wrap complex queries in parentheses to export targeted datasets for reporting tools.

sql
COPY (
    SELECT department, COUNT(*), AVG(salary) 
    FROM employees 
    GROUP BY department
) TO '/tmp/department_report.csv' WITH (FORMAT csv, HEADER);

Common COPY Errors and How to Fix Them

Bulk importing and exporting can run into unexpected problems due to file access restrictions or mismatched schemas. Below are the most frequent issues developers face and the steps to resolve them.

1. Permission Denied

This error occurs when the operating system user running the PostgreSQL service (usually the postgres system user) does not have read or write permissions on the directory containing your file. Even if your personal system login has full administrative permissions, the database process itself cannot touch the file.

Step 1. Move the target file to a public directory, such as /tmp or /var/tmp, where the system user can access it.

Step 2. Grant read access to the database engine by adjusting file and directory permissions, for example, running chmod 644 filename.csv on the file. Make sure the containing directory is also accessible to the postgres user.

2. Could Not Open File

This database message typically appears when using server-side COPY instead of client-side \copy for local files. If the path specified is correct but the file lives on a client machine, the server cannot access it.

To solve this, switch your command from SQL COPY to the client-side \copy meta-command inside the psql interface. Unlike COPY, \copy reads and writes files on the machine running psql, so it can reach files that the database server itself cannot see.

3. Invalid Input Syntax

Mismatched data types cause this error when the input file contains data that does not fit the database column definition. For example, trying to insert a text string into an integer column triggers this issue.

Review your file headers to ensure the columns align with the database table layout. If your file contains an empty string instead of a number, define the NULL option in your import statement so the database engine can translate it to a null value.

4. Extra Data After Last Expected Column

This occurs when a row in the input file contains more delimiter-separated fields than the database table has columns. It often points to a delimiter mismatch, such as when your text contains a raw comma within a standard CSV file.

Wrap the problematic text field in quotation marks within your source file. You should also ensure the FORMAT csv option is explicitly specified so the engine respects the quotation characters.

5. Encoding Errors

An encoding error happens when the text encoding of the input file does not match the database expectations. Trying to parse a UTF-8 character in a database set to SQL_ASCII or LATIN1 commonly raises this warning.

Declare the correct source file encoding using the ENCODING option during import. For example, add ENCODING 'UTF8' to the option block of your command.

Automate PostgreSQL Backups with i2Backup

Running COPY manually works well for one-off exports, but it does not scale as a long-term backup strategy. Someone still needs to remember to run the command, store the file somewhere safe, and clean up old exports before disk space runs out.

This is where a dedicated backup solution like i2Backup becomes useful. Instead of relying on manual COPY commands and cron jobs, i2Backup handles PostgreSQL backups on a schedule, with built-in retention and recovery options.

Key Features of i2Backup

  • Real-time and Scheduled Database Backup: i2Backup protects PostgreSQL alongside other mainstream databases, with support for both standalone instances and cluster environments. This removes the need to trigger COPY exports by hand every time a table needs backing up.
  • Smart Cleanup and Retention Policies: Custom retention rules automatically remove outdated backups. This solves the disk space problem that comes with manually generated CSV files piling up in a temporary directory.
  • File-level Recovery: Specific files or database entries can be restored without recovering the entire dataset. This gives you the kind of targeted restore that a single COPY FROM often cannot, especially when you only need part of the data back.
  • Restore to Anywhere: Backups can be restored to the original location or to new database hosts with cross-platform support. This helps when moving data between environments, a task that otherwise needs COPY combined with manual format adjustments.

For PostgreSQL environments running alongside other databases or virtualized infrastructure, i2Backup manages all of it from a single console, rather than requiring separate scripts for each system.

Beyond scheduled backups, businesses with stricter recovery point requirements can pair i2Backup with i2CDP, which replicates changing data at the byte level and reduces RPO to near zero. For teams managing PostgreSQL replication across multiple servers, i2Stream offers real-time database and big data replication as a complementary option.

FREE Trial for 60-Day

Conclusion

The COPY command remains one of the fastest ways to move data in and out of PostgreSQL, whether you are exporting a table for a report or restoring data after a schema change. Understanding the difference between server-side COPY and client-side \copy helps you avoid the most common file access errors covered in this guide.

For routine backups, pairing manual COPY exports with an automated solution like Info2soft’s i2Backup reduces the risk of missed backups and gives you faster, more targeted recovery options when something goes wrong.

Emma is the bridge between complex engineering and the people who need it. As a content creator at Info2soft, she spends her days translating "tech-speak" into clear, actionable stories about data resilience. She’s not just documenting software; she's uncovering how data replication and recovery actually change the way businesses run.

More Related Articles

Table of Contents:
Stay Updated on Latest Tips
Subscribe to our newsletter for the latest insights, news, exclusive content. You can unsubscribe at any time.
Subscribe
Ready to Enhance Business Data Security?
Start a 60-day free trial or view demo to see how Info2soft protects enterprise data.
Please fill out the form and submit it, our customer service representative will contact you soon.
By submitting this form, I confirm that I have read and agree to the Privacy Notice.
{{ isSubmitting ? 'Submitting...' : 'Submit' }}