40

I want to export a Postgres database into a CSV file. Is this possible?

If it is possible, then how can I do this? I have seen that we can convert a particular table into a CSV file but I don't know about a whole database.

user456584
  • 79,881
  • 11
  • 69
  • 105
Anand Singh
  • 401
  • 1
  • 5
  • 3

7 Answers7

61

I made this pl/pgsql function to create one .csv file per table (excluding views, thanks to @tarikki):

CREATE OR REPLACE FUNCTION db_to_csv(path TEXT) RETURNS void AS $$
declare
   tables RECORD;
   statement TEXT;
begin
FOR tables IN 
   SELECT (table_schema || '.' || table_name) AS schema_table
   FROM information_schema.tables t INNER JOIN information_schema.schemata s 
   ON s.schema_name = t.table_schema 
   WHERE t.table_schema NOT IN ('pg_catalog', 'information_schema')
   AND t.table_type NOT IN ('VIEW')
   ORDER BY schema_table
LOOP
   statement := 'COPY ' || tables.schema_table || ' TO ''' || path || '/' || tables.schema_table || '.csv' ||''' DELIMITER '';'' CSV HEADER';
   EXECUTE statement;
END LOOP;
return;  
end;
$$ LANGUAGE plpgsql;

And I use it this way:

SELECT db_to_csv('/home/user/dir');
-- this will create one csv file per table, in /home/user/dir/
jllodra
  • 1,142
  • 1
  • 13
  • 18
  • 4
    Want this exact solution but Not working for me giving could not open file "/home/user/Documents/public.activities.csv" for writing: Permission denied – Arihant Godha May 23 '14 at 05:05
  • Seems obvious that the user doesn't have permission to write on that path. Try with another path owned by the user who is executing the script. – jllodra May 23 '14 at 09:53
  • @ArihantGodha try changing `COPY` to `\COPY` – dayer4b Aug 18 '15 at 13:56
  • 3
    This is beautiful. Works great. Thanks! – David Watson Aug 29 '15 at 00:57
  • 2
    Brilliant script. I just modified it a bit (added one line) so it doesn't try to copy views and posted it below. Thanks for this, made my boss happy :) – tarikki May 13 '16 at 12:54
  • I launched "psql -U postgres" and no matter that path I enter I get "Permission denied". How can I fix this? fixed with SELECT db_to_csv('/tmp'); – unom Feb 02 '17 at 16:18
  • 2
    @unmircea Pretty difficult to say. You should check if your current user (postgres) has database privileges to read `information_schema.tables` and `information_schema.schemata`. Also, check if you have permissions to create and execute stored procedures. Also double check that the system user running postgresql (generally `postgres` on a *nix system) can write on the destination directory. – Ah, sorry, just read that you fixed it. Great. You can `chmod` or `chown` another folder too if you don't want to use `/tmp` :). – jllodra Feb 08 '17 at 16:29
  • 1
    @jllodra Apparently the "Permission denied" issue was because the above script tries to export Views too... Used the script in the answer below and got it working. http://stackoverflow.com/a/37210706 – unom Feb 10 '17 at 19:19
  • 3
    Thank you, saved my day! Had to export 600+ tables :D – clops May 24 '17 at 15:20
48

You can use this at psql console:

\copy (SELECT foo,bar FROM whatever) TO '/tmp/file.csv' DELIMITER ',' CSV HEADER

Or it in bash console:

psql -P format=unaligned -P tuples_only -P fieldsep=\, -c "SELECT foo,bar FROM whatever" > output_file
Piotr Olaszewski
  • 5,521
  • 5
  • 34
  • 58
18

Modified jlldoras brilliant answer by adding one line to prevent the script from trying to copy views:

CREATE OR REPLACE FUNCTION db_to_csv(path TEXT) RETURNS void AS $$
declare
   tables RECORD;
   statement TEXT;
begin
FOR tables IN 
   SELECT (table_schema || '.' || table_name) AS schema_table
   FROM information_schema.tables t INNER JOIN information_schema.schemata s 
   ON s.schema_name = t.table_schema 
   WHERE t.table_schema NOT IN ('pg_catalog', 'information_schema', 'configuration')
   AND t.table_type NOT IN ('VIEW')
   ORDER BY schema_table
LOOP
   statement := 'COPY ' || tables.schema_table || ' TO ''' || path || '/' || tables.schema_table || '.csv' ||''' DELIMITER '';'' CSV HEADER';
   EXECUTE statement;
END LOOP;
return;  
end;
$$ LANGUAGE plpgsql;
tarikki
  • 1,597
  • 2
  • 17
  • 30
4
COPY tablename TO '/tmp/products_199.csv' DELIMITER ',' CSV HEADER;

check this out

HaveNoDisplayName
  • 7,711
  • 106
  • 32
  • 44
Tombeau
  • 539
  • 4
  • 14
  • 12
    Where did you get `products_273` from? You copied and pasted directly from [this answer](http://stackoverflow.com/a/1120390/704015), didn’t you? Not cool. And shame on those who upvoted this answer. – Jezen Thomas Jan 06 '15 at 22:53
  • 1
    What's wrong with copy/pasting from the answer to another question? I don't think this is a particularly good answer, since it only applies to a single table rather than a database, but if one doesn't mind repeating the technique, it will work. – Carl G Aug 19 '16 at 21:04
  • 1
    @CarlG The matter is for references, you're not supposed to get glory from someone else's work... Instead of copy/pasting, you could just add a comment to the question and link to the answer you saw saying it may help (and then maybe mark the question as duplicated, even if here, the answer doesn't fit well) – Random Dec 07 '16 at 15:18
  • The questions are not duplicates. This one is about exporting a database and [the other](http://stackoverflow.com/a/1120390/704015) is about exporting a table. I agree that users *should* link to other answers for reference, but I disagree that users *must* link to other answers or that there should be shame for such answers. If they go through the trouble of searching for related answers and provide a responsive answer, that is useful. If it is not useful, its vote count will reflect that. That said, I think others are free to provide the missing references themselves, preferably kindly. – Carl G Dec 07 '16 at 15:50
  • I got permission denied from this answer, but not others. – Jason Liu Mar 13 '20 at 16:22
4

If you want to specify the database and user while exporting you can just modify the answer given by Piotr as follows

psql -P format=unaligned -P tuples_only -P fieldsep=\, -c "select * from tableName" > tableName_exp.csv -U <USER> -d <DB_NAME>
smishra
  • 2,322
  • 22
  • 24
1

I downloaded a copy of RazorSQL, opened the database server and right-clicked on the database and selected Export Tables and it gave me the option of CSV, EXCEL, SQL etc...

Robs
  • 8,090
  • 6
  • 36
  • 52
0

Do you want one big CSV file with data from all tables?

Probably not. You want separate files for each table or one big file with more information that can be expressed in CSV file header.

Separate files

Other answers shows how to create separate files for each table. You can query database to show you all tables with such query:

SELECT DISTINCT table_name
FROM information_schema.columns
WHERE table_schema='public'
AND position('_' in table_name) <> 1
ORDER BY 1

One big file

One big file with all tables in CSV format used by PostgreSQL COPY command can be created with pg_dump command. Output will also have all CREATE TABLE, CREATE FUNCTION etc, but with Python, Perl or similar language you can easily extract only CSV data.

Michał Niklas
  • 48,759
  • 16
  • 62
  • 100