Bulk loading with COPY

PostgreSQL · Essentials · 8 min

COPY is an order of magnitude faster than row-by-row INSERTs for imports, exports and data fixes.

COPY moves data between a table (or query) and a file or stream in one efficient operation. It is the fastest way to load data into PostgreSQL — typically many times faster than individual INSERT statements, because it avoids per-statement parsing and network round trips.

There are two flavours that look alike:

  • COPY table FROM '/path/file.csv' runs on the server: the path is on the database server's filesystem, and you need superuser or the pg_read_server_files / pg_write_server_files roles. Useless for a managed database where you can't reach the server's disk.
  • \copy table FROM 'file.csv' is a psql command: psql reads the file on your machine and streams it through COPY ... FROM STDIN. Same options, ordinary privileges. This is what you usually want.

Common options: (FORMAT csv, HEADER true), DELIMITER, NULL '', and a column list to load only some columns. To export a query result: \copy (SELECT ...) TO 'out.csv' (FORMAT csv, HEADER).

COPY is all-or-nothing: one malformed row aborts the whole load (PostgreSQL 17 added ON_ERROR ignore to skip rows with conversion errors). A robust pattern for messy files is to load into a staging table of text columns, clean with SQL, then INSERT ... SELECT into the real table. Drivers expose COPY too, for example cursor.copy() in psycopg 3.

Example

# products.csv
# sku,name,price
# A1,Pen,1.50
# B2,Notebook,4.00

psql shop <<'SQL'
CREATE TABLE product (sku text PRIMARY KEY, name text, price numeric(8,2));
\copy product FROM 'products.csv' WITH (FORMAT csv, HEADER true)
SELECT count(*) FROM product;
-- 2
\copy (SELECT sku, price * 1.2 AS price_vat FROM product) TO 'vat.csv' WITH (FORMAT csv, HEADER)
SQL

Remember

  • COPY is the fast path for bulk import and export
  • COPY reads files on the server; \copy reads them on the client
  • Load messy data into a text staging table, then clean with SQL

Watch out for

  • Using server-side COPY with a path on your laptop and getting 'could not open file'.

Check yourself

  1. You're connected with psql to a managed cloud database and want to load data.csv from your laptop. What do you use?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: www.postgresql.org/docs/current/sql-copy.html