It is possible to accomplish this in a single query using an Postgres' extension called dblink. This extension becomes available after you install postgresql-contrib package.
To be able to access it, you must add it in one of your databases.
CREATE EXTENSION IF NOT EXISTS dblink;
-- or
CREATE EXTENSION IF NOT EXISTS dblink WITH SCHEMA schema_name_here;
Using dblink function
dblink(conn_str, sql_query) you can execute dynamically generated SQL statements. The user you will use in the connection string matters, so, choose a user that can access all databases, schemas and tables involved.
As an example, the following SQL queries all databases for the table names from schemata
table, in information_schema
schema, filtering by columns named data_type
.
select datname,
schema_name,
unnest(table_names) as table_name
from (select datname,
schema_name,
(select table_names
from dblink(
'dbname=' || datname || ' user=postgres password=postgres',
'select array_agg(table_name) as table_names from ' || schema_name || '.columns where column_name = ''data_type''')
as p(table_names character varying array)) as table_names
from (select datname,
unnest(schema_name_arr) as schema_name
from (select datname,
(select schema_name_arr
from dblink(
'dbname=' || datname || ' user=postgres password=postgres',
'select array_agg(distinct nspname) as schema_name_arr from pg_catalog.pg_namespace where nspname like ''information_schema''')
as t(schema_name_arr character varying array)) as schema_name_arr
from pg_catalog.pg_database
where datistemplate is false) q
where schema_name_arr is not null
) r
) s;
The main query here is this: select array_agg(table_name) as table_names from ' || schema_name || '.columns where column_name = ''data_type''
.
Since dblink is being used in the SELECT
clause, it is restricted to return only one column. That's why I'm using the combo ARRAY_AGG + UNNEST
.
If you added dblink module into a schema, remember to use schema_name.dblink
when calling that function.
Hope it helps. Happy coding! :)