I am looking to merge a large number of individual tables into a new table in PostGIS. I have almost 100 "identical" tables so I wanted to do it automatically. There is a good answer here Merge Multiple Tables into a New Table in PostGIS but it is just for a few tables.
Asked
Active
Viewed 1,126 times
2
-
Do you have QGIS? You can use this answer: https://gis.stackexchange.com/questions/430972/virtual-layer-that-shows-the-union-of-multiple-layers-with-same-schema/430986#430986 to print out the SQL needed – BERA Jun 13 '22 at 06:25
1 Answers
5
SQL solution using a simple DO block.
This assumes you have a <target_schema>.<target_table> in place to receive the INSERTed data; I would prefer this over e.g. a collective CREATE TABLE statement (which is faster) to explicitly define column types (and typemods) and keys/constraints:
DO
$DO$
DECLARE
_shm TEXT;
_tbl TEXT;
BEGIN
FOR _shm, _tbl IN (
SELECT
pt.schemaname,
pt.tablename
FROM
pg_tables AS pt
WHERE
pt.schemaname = '<source_schema>'
AND
pt.tablename LIKE '<source_tables_common_name_pattern>'
) LOOP
RAISE NOTICE 'Merging table: %.%...', _shm, _tbl;
EXECUTE FORMAT(
$FORMAT$
INSERT INTO <target_schema>.<target_table>(<optional_column_list>) (
SELECT * FROM %1$I.%2$I
);
-- DROP TABLE %1$I.%2$I CASCADE;
$FORMAT$,
_shm, _tbl
);
END LOOP;
END;
$DO$
;
Notes:
- run the outer
LOOPquery individually prior to executing theDOblock to verfiy the correct tables are selected <source_tables_common_name_pattern>needs to be used in conjunction with the%wildcard to make sense<optional_column_list>should be used e.g. if you have an auto-incrementalPRIMARY KEYidentifier in the<target_schema>.<target_table>- you may want to also specify the exact columns in theSELECTlist inside theINSERTstatement, rather than using*- run
VACUUM ANALYZE <target_schema>.<target_table>when done - OPTIONALLY: uncomment the
DROP TABLEstatement if you want to also delete the current source table in one go - otherwise you can run this sameDOblock with only theDROP TABLEstatement afterwards
geozelot
- 30,050
- 4
- 32
- 56
-
@geozlot it works thanks. BTW, I did some slight modifications. "pt.schema_name" should be "pt.schemaname" and "pt.table_name" to "pt.tablename". Also if your schema is not the public schema you should change the search path like: 'SET search_path TO your_schema, public;' – Fardin Esmaeili Jun 17 '22 at 07:58
-
1@FardinEsmaeili I added the schema qualification to the statement. No need to set the search_path. – geozelot Jun 17 '22 at 08:28