Reputation: 14201
This might sound a bit un-realistic, but I've recently had to study the database structure of a system am maintaining remotely, and it hit me that there were some occassions when I wanted to find all columns that were linked to a given table (see, the original devs didn't create explicit relations, but instead have relations encoded in the column names!).
For example, assuming all columns referring to a column parent.parent
have the form table.somefield_parent
as the means of documenting a relationship between the two fields, how do I find all such relationships (and the tables involved) using say the standard SQL commands / in-built functions?
Any solutions for MySQL or PostgreSQL are welcome.
NOTE :
Upvotes: 3
Views: 4234
Reputation: 656706
In PostgreSQL you can query the system catalog tables.
You can also query the information_schema, which consists of views providing the standard SQL way of displaying the information. Querying the system catalogs is usually much faster, though.
To find the children of one particular parent
column:
SELECT n.nspname AS schema_name
, c.relname AS table_name
, a.attname AS column_name
FROM pg_catalog.pg_attribute a
JOIN pg_catalog.pg_class c ON c.oid = a.attrelid
JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE a.attname ~~ E'%\\_parent'
AND NOT a.attisdropped
AND c.relkind = 'r'
AND nspname !~~ E'pg\\_%';
To find all related column according to the description:
SELECT n.nspname AS parrent_schema
, c.relname AS parrent_table
, a.attname AS parrent_column
, n1.nspname AS child_schema
, c1.relname AS child_table
, a1.attname AS child_column
FROM pg_catalog.pg_attribute a
JOIN pg_catalog.pg_class c ON c.oid = a.attrelid
JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
JOIN pg_catalog.pg_attribute a1 ON a.attname = substring(a1.attname, '_(.*?)$')
JOIN pg_catalog.pg_class c1 ON c1.oid = a1.attrelid
JOIN pg_catalog.pg_namespace n1 ON n1.oid = c1.relnamespace
WHERE c.relkind = 'r'
AND c1.relkind = 'r'
AND n.nspname !~~ E'pg\\_%'
AND n1.nspname !~~ E'pg\\_%'
AND NOT a.attisdropped
AND NOT a1.attisdropped
-- AND n.nspname = 'public' -- to narrow it down to a specific schema
-- AND n1.nspname = 'public' -- to narrow it down to a specific schema
ORDER BY 1,2,3,4,5,6
This assumes that the parrent columns don't have _
in the name.
The key element is the join condition:
a.attname = substring(a1.attname, '_(.*?)$')
Upvotes: 1
Reputation: 1020
Try querying the information_schema.columns
view. It works in MySQL, but I have not tried it in Postgres. The information_schema
schema is part of the ANSI SQL standard, so Postgres will quite probably have it as well.
Other views in information_schema
include information_schema.tables
, which is useful as well
Upvotes: 7
Reputation: 11240
If you use MySQL you can use the database information_schema for that. This database contains all the meta-data for the databases on that server. As far as I know every database user has to have access to that database.
Upvotes: 0