I am using left join as a result everything should come from my left table but only matching data coming. I am not able to understand what is wrong in my query or what is missing in it. so please have a look at sample code where anyone can run and reproduce the issue.
create table #tmpModel
(
CSM_ID int,
ID INT,
ParentID INT,
DisplayInCSM Varchar(200),
Type varchar(20),
LineItemID INT
)
create table #tmpLineItem
(
ID INT,
LineItem Varchar(200),
TickerID varchar(20),
)
create table #tmpOutputDetl_CSMTuner
(
Section Varchar(200),
LineItem Varchar(200),
Period Varchar(200),
ItemValue Decimal(18,2),
Ticker varchar(20)
)
INSERT INTO #tmpModel(CSM_ID,ID,ParentID,DisplayInCSM,Type,LineItemID)
VALUES (370,1,0,'Model','SHEET',0)
,(370,2,1,'Segment Details','GROUP',0)
,(370,3,2,'LoyaltyOne','GROUP',0)
,(370,4,3,'Revenue','LINEITEM',198359)
,(370,5,4,'EBITDA','LINEITEM',198360)
,(370,6,5,'Card Services','GROUP',0)
,(370,7,6,'Diluted','LINEITEM',198342)
INSERT INTO #tmpLineItem(ID,LineItem,TickerID)
VALUES (198359,'Net Revenue','ADK')
,(198360,'EBITDA Details','ADK')
,(198342,'Diluted Shares','ADK')
INSERT INTO #tmpOutputDetl_CSMTuner (Section,LineItem,Period,ItemValue,Ticker)
VALUES ('Consensus Model','Net Revenue','2010 FYA',203.22,'ADS')
,('Consensus Model','Net Revenue','2011 FYA',203.22,'ADS')
,('Consensus Model','Net Revenue','2012 FYA',203.22,'ADS')
,('Consensus Model','EBITDA Details','2010 FYA',103.22,'ADS')
,('Consensus Model','EBITDA Details','2011 FYA',109.22,'ADS')
,('Consensus Model','EBITDA Details','2012 FYA',105.22,'ADS')
,('Key Financial','Diluted Shares','2010 FYA',55.22,'ADS')
,('Key Financial','Diluted Shares','2011 FYA',20.22,'ADS')
,('Key Financial','Diluted Shares','2012 FYA',13.22,'ADS')
;with DirectReports as
(
select CSM_ID,
ID,
ParentID,
hierarchy = format(id,'0000'),
level = 0,
DisplayInCSM,
Type,
LineItemID
from #tmpModel
where isnull(ParentID, 0) = 0
union all
select e.CSM_ID,
e.ID,
e.ParentID,
hierarchy = d.hierarchy + '.' + format(e.id,'0000'),
level = level + 1,
e.DisplayInCSM,
e.Type,
e.LineItemID
from #tmpModel e
join DirectReports d on e.ParentID = d.ID
)
/*SELECT * FROM DirectReports Order By hierarchy*/
,Cte1 as
(
SELECT AA.Section,AA.LineItem,AA.Ticker, r.DisplayInCSM, r.Type,r.hierarchy, AA.ItemValue, AA.Period
FROM DirectReports r
LEFT OUTER JOIN
(
Select b.*,L.ID AS LineItemID,L.TickerID
From #tmpOutputDetl_CSMTuner b
INNER JOIN #tmpLineItem L ON b.LineItem= L.LineItem
WHERE L.TickerID='ADK' AND b.Ticker='ADS'
) AA
ON (AA.LineItemID=r.LineItemID)
WHERE AA.Ticker = 'ADS'
)
SELECT * FROM Cte1 ORDER By hierarchy
IF OBJECT_ID(N'tempdb..#tmpModel') IS NOT NULL
BEGIN
DROP TABLE #tmpModel
END
IF OBJECT_ID(N'tempdb..#tmpLineItem') IS NOT NULL
BEGIN
DROP TABLE #tmpLineItem
END
IF OBJECT_ID(N'tempdb..#tmpOutputDetl_CSMTuner') IS NOT NULL
BEGIN
DROP TABLE #tmpOutputDetl_CSMTuner
END
Data should come with Parent child hierarchy wise
Type Group should come but not coming, only Line Item is coming.
Please guide me which area i should rectify to get the desired output.
Solved this way comment this line /WHERE AA.Ticker = 'ADS'/
Now right data is coming.
create table #tmpModel
(
CSM_ID int,
ID INT,
ParentID INT,
DisplayInCSM Varchar(200),
Type varchar(20),
LineItemID INT
)
create table #tmpLineItem
(
ID INT,
LineItem Varchar(200),
TickerID varchar(20),
)
create table #tmpOutputDetl_CSMTuner
(
Section Varchar(200),
LineItem Varchar(200),
Period Varchar(200),
ItemValue Decimal(18,2),
Ticker varchar(20)
)
INSERT INTO #tmpModel(CSM_ID,ID,ParentID,DisplayInCSM,Type,LineItemID)
VALUES (370,1,0,'Model','SHEET',0)
,(370,2,1,'Segment Details','GROUP',0)
,(370,3,2,'LoyaltyOne','GROUP',0)
,(370,4,3,'Revenue','LINEITEM',198359)
,(370,5,4,'EBITDA','LINEITEM',198360)
,(370,6,5,'Card Services','GROUP',0)
,(370,7,6,'Diluted','LINEITEM',198342)
INSERT INTO #tmpLineItem(ID,LineItem,TickerID)
VALUES (198359,'Net Revenue','ADK')
,(198360,'EBITDA Details','ADK')
,(198342,'Diluted Shares','ADK')
INSERT INTO #tmpOutputDetl_CSMTuner (Section,LineItem,Period,ItemValue,Ticker)
VALUES ('Consensus Model','Net Revenue','2010 FYA',203.22,'ADS')
,('Consensus Model','Net Revenue','2011 FYA',203.22,'ADS')
,('Consensus Model','Net Revenue','2012 FYA',203.22,'ADS')
,('Consensus Model','EBITDA Details','2010 FYA',103.22,'ADS')
,('Consensus Model','EBITDA Details','2011 FYA',109.22,'ADS')
,('Consensus Model','EBITDA Details','2012 FYA',105.22,'ADS')
,('Key Financial','Diluted Shares','2010 FYA',55.22,'ADS')
,('Key Financial','Diluted Shares','2011 FYA',20.22,'ADS')
,('Key Financial','Diluted Shares','2012 FYA',13.22,'ADS')
;with DirectReports as
(
select CSM_ID,
ID,
ParentID,
hierarchy = format(id,'0000'),
level = 0,
DisplayInCSM,
Type,
LineItemID
from #tmpModel
where isnull(ParentID, 0) = 0
union all
select e.CSM_ID,
e.ID,
e.ParentID,
hierarchy = d.hierarchy + '.' + format(e.id,'0000'),
level = level + 1,
e.DisplayInCSM,
e.Type,
e.LineItemID
from #tmpModel e
join DirectReports d on e.ParentID = d.ID
)
/*SELECT * FROM DirectReports Order By hierarchy*/
,Cte1 as
(
SELECT AA.Section,AA.LineItem,AA.Ticker, r.DisplayInCSM, r.Type,r.hierarchy, AA.ItemValue, AA.Period
FROM DirectReports r
LEFT OUTER JOIN
(
Select b.*,L.ID AS LineItemID,L.TickerID
From #tmpOutputDetl_CSMTuner b
INNER JOIN #tmpLineItem L ON b.LineItem= L.LineItem
WHERE L.TickerID='ADK' AND b.Ticker='ADS'
) AA
ON (AA.LineItemID=r.LineItemID)
/*WHERE AA.Ticker = 'ADS'*/
)
SELECT * FROM Cte1 WHERE TYPE <> 'SHEET' ORDER By hierarchy
IF OBJECT_ID(N'tempdb..#tmpModel') IS NOT NULL
BEGIN
DROP TABLE #tmpModel
END
IF OBJECT_ID(N'tempdb..#tmpLineItem') IS NOT NULL
BEGIN
DROP TABLE #tmpLineItem
END
IF OBJECT_ID(N'tempdb..#tmpOutputDetl_CSMTuner') IS NOT NULL
BEGIN
DROP TABLE #tmpOutputDetl_CSMTuner
END
I'm trying to perform a cascading delete on 15+ tables but I'm not certain that all of the requisite foreign keys have been configured properly. I would like to check for missing constraints without manually reviewing each constraint.
Is there a way to obtain a list of tables that will be affected by a cascading delete query?
Use pg_depend. Example:
create table master (id int primary key);
create table detail_1 (id int, master_id int references master(id) on delete restrict);
create table detail_2 (id int, master_id int references master(id) on delete cascade);
select pg_describe_object(classid, objid, objsubid)
from pg_depend
where refobjid = 'master'::regclass and deptype = 'n';
pg_describe_object
------------------------------------------------------
constraint detail_1_master_id_fkey on table detail_1
constraint detail_2_master_id_fkey on table detail_2
(2 rows)
deptype = 'n' means:
DEPENDENCY NORMAL - A normal relationship between separately-created
objects. The dependent object can be dropped without affecting the
referenced object. The referenced object can only be dropped by
specifying CASCADE, in which case the dependent object is dropped,
too.
Use pg_get_constraintdef() to get constraint definitions:
select
pg_describe_object(classid, objid, objsubid),
pg_get_constraintdef(objid)
from pg_depend
where refobjid = 'master'::regclass and deptype = 'n';
pg_describe_object | pg_get_constraintdef
------------------------------------------------------+------------------------------------------------------------------
constraint detail_1_master_id_fkey on table detail_1 | FOREIGN KEY (master_id) REFERENCES master(id) ON DELETE RESTRICT
constraint detail_2_master_id_fkey on table detail_2 | FOREIGN KEY (master_id) REFERENCES master(id) ON DELETE CASCADE
(2 rows)
To find the full chain of cascading dependencies we should use recursion and look into the catalog pg_constraint to get id of a dependent table.
with recursive chain as (
select classid, objid, objsubid, conrelid
from pg_depend d
join pg_constraint c on c.oid = objid
where refobjid = 'the_table'::regclass and deptype = 'n'
union all
select d.classid, d.objid, d.objsubid, c.conrelid
from pg_depend d
join pg_constraint c on c.oid = objid
join chain on d.refobjid = chain.conrelid and d.deptype = 'n'
)
select pg_describe_object(classid, objid, objsubid), pg_get_constraintdef(objid)
from chain;
Using transitive closure, one can determine the referencing and referenced tables. A caveat is that this query/view depends on the existence of Foreign Keys to determine the dependencies, and will not find tables if the FK's are missing (and the latter seems to be what the OP is asking for).
Table dependencies via Foreign Keys
CREATE OR REPLACE VIEW table_dependencies AS (
WITH RECURSIVE t AS (
SELECT
c.oid AS origin_id,
c.oid::regclass::text AS origin_table,
c.oid AS referencing_id,
c.oid::regclass::text AS referencing_table,
c2.oid AS referenced_id,
c2.oid::regclass::text AS referenced_table,
ARRAY[c.oid::regclass,c2.oid::regclass] AS chain
FROM pg_catalog.pg_constraint AS co
INNER JOIN pg_catalog.pg_class AS c ON c.oid = co.conrelid
INNER JOIN pg_catalog.pg_class AS c2 ON c2.oid = co.confrelid
-- Add this line as an input parameter if you want to make a one-off query
-- WHERE c.oid::regclass::text = 'YOUR TABLE'
UNION ALL
SELECT
t.origin_id,
t.origin_table,
t.referenced_id AS referencing_id,
t.referenced_table AS referencing_table,
c3.oid AS referenced_id,
c3.oid::regclass::text AS referenced_table,
t.chain || c3.oid::regclass AS chain
FROM pg_catalog.pg_constraint AS co
INNER JOIN pg_catalog.pg_class AS c3 ON c3.oid = co.confrelid
INNER JOIN t ON t.referenced_id = co.conrelid
WHERE
-- prevent infinite recursion by pruning paths where the last entry in
-- the path already appears somewhere else in the path
NOT (
ARRAY[ t.chain[array_upper(t.chain, 1)] ] -- an array containing the last element
<# -- "is contained by"
t.chain[1:array_upper(t.chain, 1) - 1] -- a slice of the chain,
-- from element 1 to n-1
)
)
SELECT origin_table,
referenced_table,
array_upper(chain,1) AS "depth",
array_to_string(chain,',') as chain
FROM t
);
Tables referencing a specific table
SELECT * FROM table_dependencies WHERE origin_table = 'clients';
Tables directly related to the "clients" table
SELECT *
FROM table_dependencies
WHERE referenced_table = 'clients'
AND depth = 2
ORDER BY origin_table;
Yes. you can truncate cascade in transaction and rollback. Note ROLLBACK is a key to save the data.
postgres will NOTICE you what other referencing tables will be affected.
postgres=# begin;
BEGIN
postgres=# truncate table a cascade;
NOTICE: truncate cascades to table "b"
TRUNCATE TABLE
postgres=# rollback;
ROLLBACK
Background
When dropping (or replacing) objects in PostgreSQL, if there are dependencies, the drop will fail (without specifying CASCADE).
Problem
The error message returned by the database does not list the dependent objects.
Example Solution
The query might look something like:
SELECT * FROM information_schema i, pg_depend pd WHERE
i.object_id = pd.object_id AND
i.object_type = 'TABLE' AND
i.object_schema = 'public' AND
i.object_name = 'table_with_dependents';
The objid is missing.
Related
http://postgresql.1045698.n5.nabble.com/information-schema-problem-td2144069.html
http://www.alberton.info/postgresql_meta_info.html
Question
How do you generate a list of dependent objects by name and type?
The suggested solution didn't work for me with postgresql 9.1.4
this worked:
SELECT dependent_ns.nspname as dependent_schema
, dependent_view.relname as dependent_view
, source_ns.nspname as source_schema
, source_table.relname as source_table
, pg_attribute.attname as column_name
FROM pg_depend
JOIN pg_rewrite ON pg_depend.objid = pg_rewrite.oid
JOIN pg_class as dependent_view ON pg_rewrite.ev_class = dependent_view.oid
JOIN pg_class as source_table ON pg_depend.refobjid = source_table.oid
JOIN pg_attribute ON pg_depend.refobjid = pg_attribute.attrelid
AND pg_depend.refobjsubid = pg_attribute.attnum
JOIN pg_namespace dependent_ns ON dependent_ns.oid = dependent_view.relnamespace
JOIN pg_namespace source_ns ON source_ns.oid = source_table.relnamespace
WHERE
source_ns.nspname = 'my_schema'
AND source_table.relname = 'my_table'
AND pg_attribute.attnum > 0
AND pg_attribute.attname = 'my_column'
ORDER BY 1,2;
The easy way is:
BEGIN;
DROP TABLE tablename CASCADE;
DROP VIEW viewname CASCADE;
ROLLBACK;
For PostgreSQL 9.3 onward use the following view and functions to show any user object dependency. I also updated https://wiki.postgresql.org/wiki/Pg_depend_display.
/**** Usage Examples ****
-- Examine the entire object hierarchy
SELECT report.dependency_tree('');
-- Dependencies for any relations with names containing match (in regular expression)
SELECT report.dependency_tree('match');
-- Dependencies for relations person & address
SELECT report.dependency_tree('{person,address}'::text[]);
-- Dependencies for function slice
SELECT report.dependency_tree(ARRAY['slice'::regproc]);
-- Dependencies for type hstore
SELECT report.dependency_tree(ARRAY['hstore'::regtype]);
-- Dependencies for triggers by the name updated
SELECT report.dependency_tree(ARRAY(
SELECT oid FROM pg_trigger WHERE tgname ~ 'updated'
));
-- Dependencies for foreign key constraint names starting with product
SELECT report.dependency_tree(ARRAY(
SELECT oid FROM pg_constraint
WHERE conname ~ '^product.*_fk'
));
*/
DROP VIEW IF EXISTS report.dependency;
CREATE OR REPLACE VIEW report.dependency AS
WITH RECURSIVE preference AS (
SELECT 10 AS max_depth
, 16384 AS min_oid -- user objects only
, '^(londiste|pgq|pg_toast)'::text AS schema_exclusion
, '^pg_(conversion|language|ts_(dict|template))'::text AS class_exclusion
, '{"SCHEMA":"00", "TABLE":"01", "TABLE CONSTRAINT":"02", "DEFAULT VALUE":"03",
"INDEX":"05", "SEQUENCE":"06", "TRIGGER":"07", "FUNCTION":"08",
"VIEW":"10", "MATERIALIZED VIEW":"11", "FOREIGN TABLE":"12"}'::json AS type_sort_orders
)
, dependency_pair AS (
SELECT objid
, array_agg(objsubid ORDER BY objsubid) AS objsubids
, upper(obj.type) AS object_type
, coalesce(obj.schema, substring(obj.identity, E'(\\w+?)\\.'), '') AS object_schema
, obj.name AS object_name
, obj.identity AS object_identity
, refobjid
, array_agg(refobjsubid ORDER BY refobjsubid) AS refobjsubids
, upper(refobj.type) AS refobj_type
, coalesce(CASE WHEN refobj.type='schema' THEN refobj.identity
ELSE refobj.schema END
, substring(refobj.identity, E'(\\w+?)\\.'), '') AS refobj_schema
, refobj.name AS refobj_name
, refobj.identity AS refobj_identity
, CASE deptype
WHEN 'n' THEN 'normal'
WHEN 'a' THEN 'automatic'
WHEN 'i' THEN 'internal'
WHEN 'e' THEN 'extension'
WHEN 'p' THEN 'pinned'
END AS dependency_type
FROM pg_depend dep
, LATERAL pg_identify_object(classid, objid, 0) AS obj
, LATERAL pg_identify_object(refclassid, refobjid, 0) AS refobj
, preference
WHERE deptype = ANY('{n,a}')
AND objid >= preference.min_oid
AND (refobjid >= preference.min_oid OR refobjid = 2200) -- need public schema as root node
AND coalesce(obj.schema, substring(obj.identity, E'(\\w+?)\\.'), '') !~ preference.schema_exclusion
AND coalesce(CASE WHEN refobj.type='schema' THEN refobj.identity
ELSE refobj.schema END
, substring(refobj.identity, E'(\\w+?)\\.'), '') !~ preference.schema_exclusion
GROUP BY objid, obj.type, obj.schema, obj.name, obj.identity
, refobjid, refobj.type, refobj.schema, refobj.name, refobj.identity, deptype
)
, dependency_hierarchy AS (
SELECT DISTINCT
0 AS level,
refobjid AS objid,
refobj_type AS object_type,
refobj_identity AS object_identity,
--refobjsubids AS objsubids,
NULL::text AS dependency_type,
ARRAY[refobjid] AS dependency_chain,
ARRAY[concat(preference.type_sort_orders->>refobj_type,refobj_type,':',refobj_identity)] AS dependency_sort_chain
FROM dependency_pair root
, preference
WHERE NOT EXISTS
(SELECT 'x' FROM dependency_pair branch WHERE branch.objid = root.refobjid)
AND refobj_schema !~ preference.schema_exclusion
UNION ALL
SELECT
level + 1 AS level,
child.objid,
child.object_type,
child.object_identity,
--child.objsubids,
child.dependency_type,
parent.dependency_chain || child.objid,
parent.dependency_sort_chain || concat(preference.type_sort_orders->>child.object_type,child.object_type,':',child.object_identity)
FROM dependency_pair child
JOIN dependency_hierarchy parent ON (parent.objid = child.refobjid)
, preference
WHERE level < preference.max_depth
AND child.object_schema !~ preference.schema_exclusion
AND child.refobj_schema !~ preference.schema_exclusion
AND NOT (child.objid = ANY(parent.dependency_chain)) -- prevent circular referencing
)
SELECT * FROM dependency_hierarchy
ORDER BY dependency_chain ;
-- Procedure to report depedency tree using regexp search pattern (relation-only)
CREATE OR REPLACE FUNCTION report.dependency_tree(search_pattern text)
RETURNS TABLE(dependency_tree text)
SECURITY DEFINER LANGUAGE SQL
AS $function$
WITH target AS (
SELECT objid, dependency_chain
FROM report.dependency
WHERE object_identity ~ search_pattern
)
, list AS (
SELECT
format('%*s%s %s', -4*level
, CASE WHEN object_identity ~ search_pattern THEN '*' END
, object_type, object_identity
) AS dependency_tree
, dependency_sort_chain
FROM target
JOIN report.dependency report
ON report.objid = ANY(target.dependency_chain) -- root-bound chain
OR target.objid = ANY(report.dependency_chain) -- leaf-bound chain
WHERE length(search_pattern) > 0
-- Do NOT waste search time on blank/null search_pattern.
UNION
-- Query the entire dependencies instead.
SELECT
format('%*s%s %s', 4*level, '', object_type, object_identity) AS depedency_tree
, dependency_sort_chain
FROM report.dependency
WHERE length(coalesce(search_pattern,'')) = 0
)
SELECT dependency_tree FROM list
ORDER BY dependency_sort_chain;
$function$ ;
-- Procedure to report depedency tree by specific relation name(s) (in text array)
CREATE OR REPLACE FUNCTION report.dependency_tree(object_names text[])
RETURNS TABLE(dependency_tree text)
SECURITY DEFINER LANGUAGE SQL
AS $function$
WITH target AS (
SELECT objid, dependency_chain
FROM report.dependency
JOIN unnest(object_names) AS target(objname) ON objid = objname::regclass
)
, list AS (
SELECT DISTINCT
format('%*s%s %s', -4*level
, CASE WHEN object_identity = ANY(object_names) THEN '*' END
, object_type, object_identity
) AS dependency_tree
, dependency_sort_chain
FROM target
JOIN report.dependency report
ON report.objid = ANY(target.dependency_chain) -- root-bound chain
OR target.objid = ANY(report.dependency_chain) -- leaf-bound chain
)
SELECT dependency_tree FROM list
ORDER BY dependency_sort_chain;
$function$ ;
-- Procedure to report depedency tree by oid
CREATE OR REPLACE FUNCTION report.dependency_tree(object_ids oid[])
RETURNS TABLE(dependency_tree text)
SECURITY DEFINER LANGUAGE SQL
AS $function$
WITH target AS (
SELECT objid, dependency_chain
FROM report.dependency
JOIN unnest(object_ids) AS target(objid) USING (objid)
)
, list AS (
SELECT DISTINCT
format('%*s%s %s', -4*level
, CASE WHEN report.objid = ANY(object_ids) THEN '*' END
, object_type, object_identity
) AS dependency_tree
, dependency_sort_chain
FROM target
JOIN report.dependency report
ON report.objid = ANY(target.dependency_chain) -- root-bound chain
OR target.objid = ANY(report.dependency_chain) -- leaf-bound chain
)
SELECT dependency_tree FROM list
ORDER BY dependency_sort_chain;
$function$ ;
Include nested views in the query as follows:
WITH RECURSIVE view_deps AS (
SELECT DISTINCT dependent_ns.nspname as dependent_schema
, dependent_view.relname as dependent_view
, source_ns.nspname as source_schema
, source_table.relname as source_table
FROM pg_depend
JOIN pg_rewrite ON pg_depend.objid = pg_rewrite.oid
JOIN pg_class as dependent_view ON pg_rewrite.ev_class = dependent_view.oid
JOIN pg_class as source_table ON pg_depend.refobjid = source_table.oid
JOIN pg_namespace dependent_ns ON dependent_ns.oid = dependent_view.relnamespace
JOIN pg_namespace source_ns ON source_ns.oid = source_table.relnamespace
WHERE NOT (dependent_ns.nspname = source_ns.nspname AND dependent_view.relname = source_table.relname)
UNION
SELECT DISTINCT dependent_ns.nspname as dependent_schema
, dependent_view.relname as dependent_view
, source_ns.nspname as source_schema
, source_table.relname as source_table
FROM pg_depend
JOIN pg_rewrite ON pg_depend.objid = pg_rewrite.oid
JOIN pg_class as dependent_view ON pg_rewrite.ev_class = dependent_view.oid
JOIN pg_class as source_table ON pg_depend.refobjid = source_table.oid
JOIN pg_namespace dependent_ns ON dependent_ns.oid = dependent_view.relnamespace
JOIN pg_namespace source_ns ON source_ns.oid = source_table.relnamespace
INNER JOIN view_deps vd
ON vd.dependent_schema = source_ns.nspname
AND vd.dependent_view = source_table.relname
AND NOT (dependent_ns.nspname = vd.dependent_schema AND dependent_view.relname = vd.dependent_view)
)
SELECT *
FROM view_deps
ORDER BY source_schema, source_table;
If you care about specific table attributes add this to the top portion of the recursive CTE:
JOIN pg_attribute ON pg_depend.refobjid = pg_attribute.attrelid
AND pg_depend.refobjsubid = pg_attribute.attnum
...
WHERE
source_ns.nspname = 'my_schema'
AND source_table.relname = 'my_table'
AND pg_attribute.attnum > 0
AND pg_attribute.attname = 'my_column'
pg_constraint contains all constrains in the database you can list the oid of dependent tables using confrelid and conrelid from all all the foreign key constraints
query looks like this
select confrelid,conrelid from pg_constraint where contype='f';