How to Execute Multiple SQL Files from a Single Master File in PostgreSQL


6 views

When working with PostgreSQL, you might need to execute multiple SQL scripts in sequence. This is common during database initialization, migration processes, or when applying modular schema changes. Manually running each file isn't practical, especially in automated environments.

The simplest approach is using PostgreSQL's \i meta-command within psql:

-- master_file.sql
\i /path/to/aaa.sql
\i /path/to/bbb.sql
\i /path/to/ccc.sql

For more control and error handling, create a shell script:

#!/bin/bash
psql -U username -d dbname -f aaa.sql
psql -U username -d dbname -f bbb.sql
psql -U username -d dbname -f ccc.sql

For transactional execution where you want all scripts to succeed or fail together:

-- master_file.sql
BEGIN;
\i aaa.sql
\i bbb.sql
\i ccc.sql
COMMIT;

You can add logic to check if scripts should run:

-- master_file.sql
DO $$
BEGIN
  IF (SELECT count(*) FROM information_schema.tables WHERE table_name = 'some_table') = 0 THEN
    \i aaa.sql
  END IF;
  
  \i bbb.sql
  \i ccc.sql
END
$$;

By default, psql will stop on first error. To continue after errors:

psql -v ON_ERROR_STOP=0 -f master_file.sql

When working with PostgreSQL database deployments, it's common to have multiple SQL files containing schema definitions, data migrations, or stored procedures. Executing them individually can be time-consuming and error-prone during deployments or development setup.

The simplest approach is using PostgreSQL's built-in \\i command in psql:

-- master_script.sql
\\i /path/to/aaa.sql
\\i /path/to/bbb.sql
\\i /path/to/ccc.sql

For more control, create a shell script that pipes files to psql:

#!/bin/bash
psql -U username -d dbname -f aaa.sql
psql -U username -d dbname -f bbb.sql
psql -U username -d dbname -f ccc.sql

Important: By default, each file executes in its own transaction. To wrap everything in a single transaction:

BEGIN;
\\i aaa.sql
\\i bbb.sql
\\i ccc.sql
COMMIT;

For production deployments, consider adding error checking:

\\set ON_ERROR_STOP on
\\i aaa.sql
\\i bbb.sql
\\i ccc.sql

For advanced scenarios with many files, use a PL/pgSQL script with dynamic SQL:

DO $$
DECLARE
    file_list text[] := ARRAY['aaa.sql','bbb.sql','ccc.sql'];
    file_name text;
BEGIN
    FOREACH file_name IN ARRAY file_list LOOP
        EXECUTE format('\\i %s', file_name);
    END LOOP;
END $$;

For portable scripts across environments:

\\set base_path '/path/to/sql/files'
\\i :base_path/aaa.sql
\\i :base_path/bbb.sql
\\i :base_path/ccc.sql