How can I specify the schema to run an sql file against in the Postgresql command line

I run scripts against my database like this...

psql -d myDataBase -a -f myInsertFile.sql

The only problem is I want to be able to specify in this command what schema to run the script against. I could call set search_path='my_schema_01' but the files are supposed to be portable. How can I do this?

155156 次浏览

You can create one file that contains the set schema ... statement and then include the actual file you want to run:

Create a file run_insert.sql:

set schema 'my_schema_01';
\i myInsertFile.sql

Then call this using:

psql -d myDataBase -a -f run_insert.sql

I'm using something like this and works very well:* :-)

(echo "set schema 'acme';" ; \
cat ~/git/soluvas-framework/schedule/src/main/resources/org/soluvas/schedule/tables_postgres.sql) \
| psql -Upostgres -hlocalhost quikdo_app_dev

Note: Linux/Mac/Bash only, though probably there's a way to do that in Windows/PowerShell too.

More universal way is to set search_path (should work in PostgreSQL 7.x and above):

SET search_path TO myschema;

Note that set schema myschema is an alias to above command that is not available in 8.x.

See also: http://www.postgresql.org/docs/9.3/static/ddl-schemas.html

I was facing similar problems trying to do some dat import on an intermediate schema (that later we move on to the final one). As we rely on things like extensions (for example PostGIS), the "run_insert" sql file did not fully solved the problem.

After a while, we've found that at least with Postgres 9.3 the solution is far easier... just create your SQL script always specifying the schema when refering to the table:

CREATE TABLE "my_schema"."my_table" (...); COPY "my_schema"."my_table" (...) FROM stdin;

This way using psql -f xxxxx works perfectly, and you don't need to change search_paths nor use intermediate files (and won't hit extension schema problems).

Main Example

The example below will run myfile.sql on database mydatabase using schema myschema.

psql "dbname=mydatabase options=--search_path=myschema" -a -f myfile.sql

The way this works is the first argument to the psql command is the dbname argument. The docs mention a connection string can be provided.

If this parameter contains an = sign or starts with a valid URI prefix (postgresql:// or postgres://), it is treated as a conninfo string

The dbname keyword specifies the database to connect to and the options keyword lets you specify command-line options to send to the server at connection startup. Those options are detailed in the server configuration chapter. The option we are using to select the schema is search_path.

Another Example

The example below will connect to host myhost on database mydatabase using schema myschema. The = special character must be url escaped with the escape sequence %3D.

psql postgres://myuser@myhost?options=--search_path%3Dmyschema

The PGOPTIONS environment variable may be used to achieve this in a flexible way.

In an Unix shell:

PGOPTIONS="--search_path=my_schema_01" psql -d myDataBase -a -f myInsertFile.sql

If there are several invocations in the script or sub-shells that need the same options, it's simpler to set PGOPTIONS only once and export it.

PGOPTIONS="--search_path=my_schema_01"
export PGOPTIONS


psql -d somebase
psql -d someotherbase
...

or invoke the top-level shell script with PGOPTIONS set from the outside

PGOPTIONS="--search_path=my_schema_01"  ./my-upgrade-script.sh

In Windows CMD environment, set PGOPTIONS=value should work the same.

This works for me:

psql postgresql://myuser:password@myhost/my_db -f myInsertFile.sql

In my case, I wanted to add schema to a file dynamically so that whatever schema name user will provide from the cli, I will run sql file with that provided schema name. For this, I replaced some text in the sql file. First I added \{\{schema}} in the file like this

CREATE OR REPLACE FUNCTION \{\{schema}}.usp_dailygaintablereportdata(

then replace \{\{schema}} dynamically with user provided schema name with the help of sed command

sed -i "s/\{\{schema}}/$pgSchemaName/" $filename
result=$(psql -U $user -h $host -p $port -d $dbName -f "$filename" 2>&1)
sed -i "s/$pgSchemaName/\{\{schema}}/" $filename

First replace is done, then target file is run and then again our replace is reverted back