A table\'s rows were mistakenly deleted from the database. We have a db backup which results in a sql file that can restored like so:
psql -h localhost -d pr
I've recently written a step by step guide on how to restore individual postgres tables.
In short it doesn't work with SQL backups, you need to switch to pg_dump
to generate backup files:
pg_dump.exe --host localhost --port 5432 --username "postgres" --schema "public" --format custom --blobs --verbose --file "my_database.dump" "my_database"
Then, whenever you need to restore a specific table for data recovery or bug investigating purposes, you'll have to:
my_database_restored
my_table
in the empty databasepg_restore
to selectively import desired table’s data:pg_restore.exe -U postgres --data-only -d "my_database_restored" -t "my_table" "my_database.dump"
I'm not aware of any tool for this, but this one-liner extracts precious_table
from my_backup.sql
file:
sed -n '/^COPY precious_table /,/^\\\.$/p' my_backup.sql
I've write some commands to restore only the DATA for one table, from a plain text pg_dumpall. Inspired from Zouppen, thanks. That's for french readers.
Restaurer les DONNÉES d'une table à partir d'une sauvegarde 'plain text SQL' faite, par exemple, avec pg_dumpall
$ cd /data/bkp/ $ ls -l
$ sed -n '/^COPY public.ma_table /,/^\\\.$/p' pg_full_bak.dmp > ma_table.sql $ ls -l
s'assurer que les données sont bien celles attendues
$ less ma_table.sql
se connecter sur la base [db_name] contenant la table [ma_table] vide à restaurer, avec un compte ayant les droits en écriture sur la table [ma_table]
$ psql -d db_name
vérifier que la table à restaurer [ma_table] est bien vide
postgres@db_name# select count(*) nb from ma_table ; +------+ | nb | +------+ | 0 | +------+
=> importer les données effacées <=
postgres@db_name# \i ma_table.sql
vérifier que les données ont bien été importées
postgres@db_name# select count(*) nb from ma_table ; +-------+ | nb | +-------+ | 9876 | +-------+
That's working for me under pg 9.3
The easy way : steps 2, 4 & 6
You can use grep + sed in roder to get table data:
First, you need to identify boundaries:
$ fgrep -Ehn '^(COPY |CREATE TABLE )' db.sql
49:CREATE TABLE test (
60:CREATE TABLE test2 (
71:CREATE TABLE test3 (
82:COPY test (i) FROM stdin;
100090:COPY test2 (i) FROM stdin;
200098:COPY test3 (i) FROM stdin;
In order to extract data for table test2:
sed -n '100090,200097p' < db.sql | sed -e 's/^COPY test2/COPY new_table_name/' > new_table_name.sql
Note, you need to subtract one from the second number (i.e exclude next copy stmt)
Now, you can load new_table_name.sql
and restore data which you need.
Now, you can load data into new table
Don't do SQL backups if you need single table restore, etc. Use pg_dump's -Fc option - the "custom" format. This can be restored using pg_restore
. Selective restore is possible, as are all sorts of other handy features. pg_restore
can convert a custom-format dump into an SQL dump later if you need it.
If you're stuck with an existing dump, your only options are:
Use a text editor to extract the target table data to a separate file and just restore that; or
Restore the dump to a throwaway database then use pg_dump
to take a selective dump including just that table. Since it's throwaway, you can use a separate Pg instance on some unloaded fast-but-unsafe machine where you turn on all the "make it fast but eat my data if you like" options like fsync=off
. You should NEVER set that in production.
I happen to have pg_dumpall dump around. And I would like to restore table named users
from the database named edc
, as you most likely will have equally named tables in different databases and even schemas.
For my case, the following sed
oneliner works:
sed -ne '/^\\connect edc/,/^\\connect/{/\susers\(\s\|$\)/,/;\|\\\./p}' pg92.dump
What it does:
/^\\connect edc/,/^\\connect/
limits the search to be the scope of my database;{…}
will perform all inside commands for the range;/\susers\(\s\|$\)/
matches all lines with users
on it's own, including at the end of the line;/;\|\\\./
matches lines with ;
or containing \.
p
forces the matching lines to be outputted (note, that sed is invoked with -n
).Depending on the complexity of your data, you might need to tweak this.
All you have to do is to pipe sed
output to the psql
command with right switches.