The list of all the queries

Do not leave out the referential constraints (pairs of tables)

Query goal: Try to find missing foreign key constraints. Find pairs of base table columns that have the similar name, perhaps the same type, and that are not associated through a foreign key relationship.
Notes about the query: Find pairs of columns where one column (x) is a primary key or unique constraint column and another (y) is a column that is not a part of any foreign key. Return pairs that satisfy the following conditions. Firstly, there cannot be a reverse foreign key constraint where x is a foreign key column that refers to the column y. Secondly, one of the additional conditions must hold. 1) x and y have the same type and the same name AND x and y are columns of different tables. 2) x has name "id", "kood","code", or "nr" AND y name is x table name with the possible prefix or suffix "id", "kood","code", or "nr" (for instance, table Person has column id and table Worker has column worker_id). 3) x name is the same as the x table name AND y name is x name with the possible prefix or suffix "id", "kood","code", or "nr" AND x and y are columns of different tables (for instance, table Person has column person and table Worker has column person_id).
Query type: Problem detection (Each row in the result could represent a flaw in the design)
Query reliability: Low (Many false-positive results)
Query license: MIT License
Fixing suggestion: Declare foreign key constraints.
Data source: INFORMATION_SCHEMA+system catalog
SQL query: Click on query to copy it

WITH key_columns AS (SELECT kcu.table_schema, kcu.table_name, kcu.column_name, c.data_type
FROM INFORMATION_SCHEMA.key_column_usage AS kcu INNER JOIN
INFORMATION_SCHEMA.columns AS c
USING (table_schema, table_name, column_name)
WHERE (constraint_schema, constraint_name) IN
(SELECT constraint_schema, constraint_name
FROM INFORMATION_SCHEMA.table_constraints
WHERE constraint_type IN ('PRIMARY KEY','UNIQUE') AND 
constraint_schema NOT IN (SELECT schema_name
FROM INFORMATION_SCHEMA.schemata
WHERE schema_name<>'public' AND
schema_owner='postgres' AND schema_name IS NOT NULL))),

fk as (select
o.conname,
(select nspname from pg_namespace where oid=f.relnamespace) as foreign_schema,
f.relname as foreign_table,
f.oid as foreign_table_oid,
o.confkey AS foreign_col,
(select nspname from pg_namespace where oid=c.relnamespace) as target_schema,
c.relname as target_table,
c.oid as target_table_oid,
o.conkey AS target_col
from pg_constraint o inner join pg_class c on c.oid = o.conrelid
inner join pg_class f on f.oid = o.confrelid
where o.contype = 'f'),
fk_unnest as (select conname, foreign_schema, foreign_table,  foreign_table_oid, foreign_col, foreign_col_num, target_schema, target_table, target_table_oid, target_col, target_col_num, ordin
from fk, unnest(fk.foreign_col, fk. target_col) with ordinality as f(foreign_col_num, target_col_num, ordin)),
fk_with_names as (select conname, foreign_schema, foreign_table, a_foreign.attname as foreign_col, target_schema, target_table, a_target.attname as target_col
from fk_unnest fk inner join pg_attribute a_foreign on fk.foreign_col_num = a_foreign.attnum and fk.foreign_table_oid = a_foreign.attrelid and a_foreign.attisdropped = false
inner join pg_attribute a_target on fk.target_col_num = a_target.attnum and fk.target_table_oid = a_target.attrelid and a_target.attisdropped = false),

all_non_fk_columns AS (SELECT table_schema, table_name, column_name, data_type
FROM INFORMATION_SCHEMA.columns AS c
WHERE table_schema NOT IN (SELECT schema_name
FROM INFORMATION_SCHEMA.schemata
WHERE schema_name<>'public' AND
schema_owner='postgres' AND schema_name IS NOT NULL)
AND (table_schema, table_name) IN (SELECT table_schema, table_name
FROM INFORMATION_SCHEMA.tables
WHERE table_type='BASE TABLE')
AND NOT EXISTS (SELECT 1
FROM fk_with_names AS fwn
WHERE c.table_schema=fwn.target_schema
AND c.table_name=fwn.target_table
AND c.column_name=fwn.target_col))

SELECT key_columns.table_schema AS primary_table_schema, key_columns.table_name AS
primary_table_name, key_columns.column_name AS primary_column_name,
all_non_fk_columns.table_schema AS dependent_table_schema, all_non_fk_columns.table_name AS
dependent_table_name, all_non_fk_columns.column_name AS dependent_column_name
FROM key_columns, all_non_fk_columns
WHERE (key_columns.data_type=all_non_fk_columns.data_type) AND
((Upper(key_columns.column_name)=Upper(all_non_fk_columns.column_name) AND 
(NOT (key_columns.table_schema=all_non_fk_columns.table_schema AND key_columns.table_name=all_non_fk_columns.table_name)))
OR
(Upper(key_columns.column_name) IN ('ID','KOOD','CODE','NR') AND
Upper(key_columns.table_name)=regexp_replace(translate(Upper(all_non_fk_columns.column_name),'_',''),'(ID|KOOD|CODE|NR)',''))
OR
(Upper(key_columns.column_name)=Upper(key_columns.table_name) AND
Upper(key_columns.table_name)=regexp_replace(translate(Upper(all_non_fk_columns.column_name),'_',''),'(ID|KOOD|CODE|NR)','') AND
(NOT (key_columns.table_schema=all_non_fk_columns.table_schema AND key_columns.table_name=all_non_fk_columns.table_name))))
AND NOT EXISTS (SELECT 1 
FROM fk_with_names AS R
WHERE R.foreign_schema =all_non_fk_columns.table_schema AND 
R.foreign_table= all_non_fk_columns.table_name AND 
R.foreign_col=all_non_fk_columns.column_name AND 
R.target_schema = key_columns.table_schema AND 
R.target_table= key_columns.table_name AND 
R.target_col=key_columns.column_name)
ORDER BY key_columns.table_schema, key_columns.table_name, all_non_fk_columns.table_schema, all_non_fk_columns.table_name;

Categories where the query belongs to

Category nameCategory description
Database design antipatternsQueries of this category provide information about possible occurrences of SQL database design antipatterns.
Relationships between tablesQueries of this category provide information about how database tables are connected to each other and whether such connections have been explicitly defined and whether it has been done correctly.
Validity and completenessQueries of this category provide information about whether database design represents the world (domain) correctly (validity) and whether database design captures all the information about the world (domain) that is correct and relevant (completeness).

Reference materials for further reading

Reference
This is one of the antipatterns from the Bill Karwin's book of SQL antipatterns. See Chapter 5: Keyless Entry.
Rule 7 in: Delplanque, J., Etien, A., Auverlot, O., Mens, T., Anquetil, N., Ducasse, S.: CodeCritics applied to database schema: Challenges and first results. In: 2017 IEEE 24th International Conference on Software Analysis, Evolution and Reengineering (SANER), pp. 432-436. IEEE, (2017).
Weber, J.H., Cleve, A., Meurice, L., Ruiz, F.J.B.:. Managing technical debt in database schemas of critical software. In: Sixth International Workshop on Managing Technical Debt, pp. 43-46. IEEE (2014).
Smell "Missing constraints": Sharma, T., Fragkoulis, M., Rizou, S., Bruntink, M. and Spinellis, D.: Smelly relations: measuring and understanding database schema quality. In: Proceedings of the 40th International Conference on Software Engineering: Software Engineering in Practice, pp. 55-64. ACM, (2018).
Mistake (4): https://www.red-gate.com/simple-talk/sql/database-administration/five-simple--database-design-errors-you-should-avoid/

The list of all the queries