I tried to export a select query result to a csv file. I used Postgres \copy metacommand and command line (psql) to do it. But I got a Syntax error and can't understand why. The Query looks fine to me. Maybe the reason for using metacommand instead of COPY?
The query
\copy
(
SELECT geo_name, state_us_abbreviation, housing_unit_count_100_percent
FROM us_counties_2010
ORDER BY housing_unit_count_100_percent DESC
LIMIT 20
)
TO '/username/Desktop/us_counties_2010_export.csv'
WITH(FORMAT CSV, HEADER, DELIMITER '|');
Error message
ERROR: syntax error at or near "TO"
LINE 7: TO '/username/Desktop/us_counties_2010_export.csv'
\copy is a metacommand given to psql, not a regular command sent to the server. So like other metacommands, the entire \copy command must all be given on one line and doesn't end in a ; but rather a newline.
If you look closely, you will see the first error you got was \copy: arguments required
DB2 command to Postgres command.
db2 IMPORT FROM test.csv OF DEL MODIFIED BY USEDEFAULTS COMMITCOUNT 100000 "INSERT_UPDATE INTO TEST.person (name,old,sex)" > ${TEMPTXT}
How can i use postgres command to do the same thing like this db2 command to import from file to insert and update the table ?
Postgres has COPY, but it doesn't perform update.So, first run COPY into a TEMP table and then merge into main table.
For a comma delimiter,
CREATE TEMP TABLE TEST.tmp_person (name text,old text,sex text)
COPY TEST.tmp_person FROM test.csv WITH DELIMITER ',' CSV
-- ^temp table
There are various techniques in Postgres to do INSERT_UPDATE or merge. Refer this post. Use proper casting to appropriate target data types while inserting/updating.
I'm trying to export the results of my SQL query to a CSV file but it doesn't seem to work. I'm using postgresql version 10.4
\copy (select 1,2) To '/test.csv' With CSV DELIMITER ',';
This gives the follwing error:
ERROR: syntax error at or near "("
LINE 1: COPY ( select 1,2 ) TO STDOUT With CSV DELIMITER ',';
Running the query by itself works fine. I've also tried removing the brackets.
Any help appreciated! Thanks
Above query should work fine. Make sure you write the above query in single line and not multi-line.
This should work.
\copy (select 1,2) to '/test1.csv' with delimiter ',' csv header quote as '"'
I'm trying to write a script that copies data from a crosstab query to a .csv file in Postgres 8.4. I am able to run the command in the psql command line but when I put the command in a file and run it using the -f option, I get a syntax error.
Here's an example of what I'm looking at (from this great answer):
CREATE TEMP TABLE t (
section text
,status text
,ct integer
);
INSERT INTO t VALUES
('A', 'Active', 1), ('A', 'Inactive', 2)
,('B', 'Active', 4), ('B', 'Inactive', 5)
, ('C', 'Inactive', 7);
\copy (
SELECT * FROM crosstab(
'SELECT section, status, ct
FROM t
ORDER BY 1,2'
,$$VALUES ('Active'::text), ('Inactive')$$)
AS ct ("Section" text, "Active" int, "Inactive" int)
) TO 'test.csv' HEADER CSV
I then run this and get the following syntax error:
$ psql [system specific] -f copy_test.sql
CREATE TABLE
INSERT 0 5
psql:copy_test.sql:12: \copy: parse error at end of line
psql:copy_test.sql:19: ERROR: syntax error at or near ")"
LINE 7: ) TO 'test.csv' HEADER CSV
^
A similar exercise doing just a simple query without crosstab works without incident.
What is causing the syntax error and how can I copy this table to a csv file using script file?
psql thinks your first command is just \copy ( and the lines below that are from another unrelated statement. Meta-commands aren't spread on multiple lines, because newline is is a terminator for them.
Relevant excerpts from psql manpage with some emphasis added:
Meta-Commands
Anything you enter in psql that begins with an unquoted backslash is a
psql meta-command that is processed by psql itself. These commands
make psql more useful for administration or scripting. Meta-commands
are often called slash or backslash commands.
....
....(skipped)
Parsing for arguments stops at the end of the line, or when another
unquoted backslash is found. An unquoted backslash is taken as the
beginning of a new meta-command. The special sequence \\ (two
backslashes) marks the end of arguments and continues parsing SQL
commands, if any. That way SQL and psql commands can be freely mixed
on a line. But in any case, the arguments of a meta-command cannot
continue beyond the end of the line.
So the first error is that \copy ( failing, then the lines below are interpreted as an independent SELECT which looks fine until line 7 when there is a spurious closing parenthesis.
As told in the comments, the fix would be to cram the whole meta-command into a single line.
As with this answer, create a multi-line VIEW with a single-line \copy command, e.g.:
CREATE TEMP TABLE t (
section text
,status text
,ct integer
);
INSERT INTO t VALUES
('A', 'Active', 1), ('A', 'Inactive', 2)
,('B', 'Active', 4), ('B', 'Inactive', 5)
, ('C', 'Inactive', 7);
CREATE TEMP VIEW v1 AS
SELECT * FROM crosstab(
'SELECT section, status, ct
FROM t
ORDER BY 1,2'
,$$VALUES ('Active'::text), ('Inactive')$$)
AS ct ("Section" text, "Active" int, "Inactive" int);
\copy (SELECT * FROM v1) TO 'test.csv' HEADER CSV
-- optional
DROP VIEW v1;
The answers listed here explain the reasoning quite clearly. Here is a small hack that allows you to have your sql contain multiple lines and work with psql.
# Using a file
psql -f <(tr -d '\n' < ~/s/test.sql )
# or
psql < <(tr -d '\n' < ~/s/test.sql )
# Putting the SQL using a HEREDOC
cat <<SQL | tr -d '\n' | \psql mydatabase
\COPY (
SELECT
provider_id,
provider_name,
...
) TO './out.tsv' WITH( DELIMITER E'\t', NULL '', )
SQL
According to the psql documentation:
-f filename
--file filename
Use the file filename as the source of commands instead of reading commands interactively. After the file is processed, psql terminates. This is in many ways equivalent to the internal command \i.
If filename is - (hyphen), then standard input is read.
Using this option is subtly different from writing psql < filename. In general, both will do what you expect, but using -f enables some nice features such as error messages with line numbers. There is also a slight chance that using this option will reduce the start-up overhead. On the other hand, the variant using the shell's input redirection is (in theory) guaranteed to yield exactly the same output that you would have gotten had you entered everything by hand.
This would be one of those cases where the -f option treats your input differently from the command line. Removing your newlines worked, redirecting the original file to psql's stdin would likely have worked as well.
is possible in PSQL console export file with current date on the end of the file name?
The name of the exported file should be like this table_20140710.csv is it possible to do this dynamically? - the format of the date can be different than the above it isn't so much important.
This is example what i mean:
\set curdate current_date
\copy (SELECT * FROM table) To 'C:/users/user/desktop/table_ ' || :curdate || '.csv' WITH DELIMITER AS ';' CSV HEADER
The exception of the \copy meta command not expanding variables is (meanwhile) documented
Unlike most other meta-commands, the entire remainder of the line is always taken to be the arguments of \copy, and neither variable interpolation nor backquote expansion are performed in the arguments.
To workaround you can build, store and execute the command in multiple steps (similar to the solution Clodoaldo Neto has given):
\set filename 'my fancy dynamic name'
\set command '\\copy (SELECT * FROM generate_series(1, 5)) to ' :'filename'
:command
With this, you need to double (escape) the \ in the embedded meta command. Keep in mind that \set concatenates all further arguments to the second one, so quote spaces between the arguments. You can show the command before execution (:command) with \echo :command.
As an alternative to the local \set command, you could also build the command server side with SQL (the best way depends on where the dynamic content is originating):
SELECT '\copy (SELECT * FROM generate_series(1, 5)) to ''' || :'filename' || '''' AS command \gset
Dynamically build the \copy command and store it in a file. Then execute it with \i
First set tuples only output
\t
Set the output to a file
\o 'C:/users/user/desktop/copy_command.txt'
Build the \copy command
select format(
$$\copy (select * from the_table) To 'C:/users/user/desktop/table_%s.csv' WITH DELIMITER AS ';' CSV HEADER$$
, current_date
);
Restore the output to stdout
\o
Execute the generated command from the file
\i 'C:/users/user/desktop/copy_command.txt'