58

Is it possible to use a Linux environment variable inside a .sql file? I'm using the copy/select query to write to an output file, and I'll like to put that directory in a variable. So I want to do something like:

COPY (SELECT * FROM a)
TO $outputdir/a.csv

Outputdir would be set in my environment. Is this possible?

1
  • NB: As is, even if you did succeed in substituting the variable, it won't work as expected because COPY ... TO expects the output file path to be single quoted. See here: postgresql.org/docs/9.2/static/sql-copy.html Commented Sep 10, 2013 at 19:59

3 Answers 3

82

You can store the result of a shell command inside a psql variable like this:

\set afile `echo "$outputdir/a.csv"`
COPY (SELECT * FROM a) TO :'afile';

Another (better in my opinion) solution is to use only psql variables, see this answer of mine about psql variables, which is similar to your example. A example for your case would be:

\set outputdir '/path/to/output'
\set afile :outputdir '/a.csv'
COPY (SELECT * FROM a) TO :'afile';

Note that, in the example, you need to set the variable inside the script file, but you can skip the first line if you set it when you call psql:

psql --set=outputdir="$outputdir" <conn parameters> -f /path/to/yourscript.sql
Sign up to request clarification or add additional context in comments.

7 Comments

I was very excited about this answer, but it's not quite working for me. Using your first example, 'afile' just evaluates to 'echo "$outputdir/a.csv"'. Nothing inside the quotes is expanded.
The examples work for me on psql 9.2.4. What version of psql are you using?
According to the psql docs for 9.0, you should be able to use backquotes to return the output from the shell. Thus, that should really not be outputting the echo part especially, and the variable ought to be subject to expansion as well. Did you copy that code verbatim and are you typed it out manually, are sure you didn't maybe use a single quote rather than a backquote?
YES! Single quote is exactly what I used. Thanks so much for that insight!!
The echo $outputdir syntax for accessing environment variables works perfectly on Unix. On Windows a different incantation is required; see my answer below.
|
2

This appears to work for your use case, provided you single quote the output file name as I mentioned. It will escape any double quotes as well contained within the SQL.

psql -c "$(eval echo '"' $(<envvars.sql | sed 's/"/\\"/g') '"')"

Of course, note that if your file contains any dollar quoted variables, the shell is going to try to interpret as a variable, and your script will break, so you will need to escape any dollar signs you need preserved literally with a backslash.

See also the second snippet in the accepted answer to this question for a possibly more robust answer.

Comments

2

The accepted answer is correct for PostgreSQL running on Unix. Under Windows a different incantation is required for obtaining the value of the environment variable from the CMD shell and for avoiding the carriage return returned by the echo command.

\set afile `set /p=%outputdir%/a.csv`
COPY (SELECT * FROM a) TO :'afile';

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.