![](/img/trans.png)
[英]In Oracle SQL , how can I find which tables reference a specific column (i.e have it as foreign key )?
[英]How can I find tables which reference a particular row via a foreign key?
給定這樣的結構:
CREATE TABLE reference_table (
reference_table_key numeric NOT NULL,
reference_value numeric,
CONSTRAINT reference_table_pk PRIMARY KEY (reference_table_key)
);
CREATE TABLE other_table (
other_table_key numeric NOT NULL,
reference_table_key numeric,
CONSTRAINT other_table_pk PRIMARY KEY (other_table_key),
ONSTRAINT other_table_reference_fk FOREIGN KEY (reference_table_key)
REFERENCES reference_table (reference_table_key) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE SET NULL
);
CREATE TABLE another_table (
another_table_key numeric NOT NULL,
do_stuff_key numeric,
CONSTRAINT another_table_pk PRIMARY KEY (another_table_key),
ONSTRAINT another_table_reference_fk FOREIGN KEY (do_stuff_key)
REFERENCES reference_table (reference_table_key) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE SET NULL
);
--there are 50-60 tables which have similar foreign key references to reference_table
我想編寫一個查詢,告訴我other_table和another_table中的主鍵以及reference_value為NULL的更多表。
在偽代碼中:
SELECT table_name, table_primary_key, table_fk_column_name
FROM ?????? some PG table ???????, reference_table
WHERE reference_table.reference_value IS NULL;
結果如下所示:
table_name | table_primary_key | table_fk_column_name | reference_table_pk
---------------------------------------------------------------------------
other_table | 2 | reference_table_key | 7
other_table | 4 | reference_table_key | 56
other_table | 45 | reference_table_key | 454
other_table | 65765 | reference_table_key | 987987
other_table | 11 | reference_table_key | 3213
another_table | 3 | do_stuff_key | 4645
another_table | 5 | do_stuff_key | 43546
another_table | 7 | do_stuff_key | 464356
unknown_table | 1 | unkown_column_key | 435435
unknown_table | 1 | some_other_column_key | 34543
unknown_table | 3 | unkown_column_key | 124
unknown_table | 3 | some_other_column_key | 123
這類似於但不是Postgres的重復:SQL列出表外鍵 。 這個問題說明了表的結構。 我想找到特定的實例。
本質上,如果我DELETE FROM reference_table WHERE reference_value IS NULL;
,Postgres的有做一些內部找出它需要一套reference_table_key
在第2行中other_table
為NULL。 我想看看這些行是什么。
有查詢可以做到這一點嗎? 有沒有可以傳遞給DELETE調用的修飾符,可以告訴我該DELETE將影響哪些表/行/列?
此查詢生成DML語句以查找所有表中的所有行 ,其中一列具有引用另一個表的外鍵約束,但在該列中保留NULL
值:
WITH x AS (
SELECT c.conrelid::regclass AS tbl
, c.confrelid::regclass AS ftbl
, quote_ident(k.attname) AS fk
, quote_ident(pf.attname) AS pk
FROM pg_constraint c
JOIN pg_attribute k ON (k.attrelid, k.attnum) = (c.conrelid, c.conkey[1])
JOIN pg_attribute f ON (f.attrelid, f.attnum) = (c.confrelid, c.confkey[1])
LEFT JOIN pg_constraint p ON p.conrelid = c.conrelid AND p.contype = 'p'
LEFT JOIN pg_attribute pf ON (pf.attrelid, pf.attnum)
= (p.conrelid, p.conkey[1])
WHERE c.contype = 'f'
AND c.confrelid = 'fk_tbl'::regclass -- references to this tbl
AND f.attname = 'fk_tbl_id' -- and only to this column
)
SELECT string_agg(format(
'SELECT %L AS tbl
, %L AS pk
, %s::text AS pk_val
, %L AS fk
, %L AS ftbl
FROM %1$s WHERE %4$s IS NULL'
, tbl
, COALESCE(pk 'NONE')
, COALESCE(pk 'NULL')
, fk
, ftbl), '
UNION ALL
') || ';'
FROM x;
產生這樣的查詢:
SELECT 'some_tbl' AS tbl
, 'some_tbl_id' AS pk
, some_tbl_id::text AS pk_val
, 'fk_tbl_id' AS fk
, 'fk_tbl' AS ftbl
FROM some_tbl WHERE fk_tbl_id IS NULL
UNION ALL
SELECT 'other_tbl' AS tbl
, 'other_tbl_id' AS pk
, other_tbl_id::text AS pk_val
, 'some_name_id' AS fk
, 'fk_tbl' AS ftbl
FROM other_tbl WHERE some_name_id IS NULL;
產生如下輸出:
tbl | pk | pk_val | fk | ftbl
-----------+--------------+--------+--------------+--------
some_tbl | some_tbl_id | 49 | fk_tbl_id | fk_tbl
some_tbl | some_tbl_id | 58 | fk_tbl_id | fk_tbl
other_tbl | other_tbl_id | 66 | some_name_id | fk_tbl
other_tbl | other_tbl_id | 67 | some_name_id | fk_tbl
不能可靠地覆蓋多列外鍵或主鍵 。 您必須為此使查詢更復雜。
我投所有的主鍵值 text
涵蓋所有類型。
調整或刪除這些行,以找到指向另一個或任何列/表的外鍵:
AND c.confrelid = 'fk_tbl'::regclass AND f.attname = 'fk_tbl_id' -- and only this column
已在PostgreSQL 9.1.4中測試。 我使用pg_catalog
表。 實際上,我在這里使用的所有內容都不會改變,但這在主要版本中不能保證。 如果您需要它在更新中可靠地工作,請使用information_schema
表重寫它。 那比較慢,但是可以肯定。
我沒有在生成的DML腳本中quote_ident()
表名,因為quote_ident()
會因架構限定名而失敗。 您有責任避免使用有害的表名,例如"users; DELETE * FROM users;"
。 花費更多的精力,您可以分別檢索架構名稱和表名稱,並使用quote_ident()
。
我的第一個解決方案與您的要求有一些細微的差別,因為您所描述的(根據我的理解)不存在。 值NULL
為“未知”,無法引用。 如果你真的想找到一個行NULL
在具有FK約束指向它(不特定的行與列值NULL
值,當然),那么查詢可以大大簡化:
WITH x AS (
SELECT c.confrelid::regclass AS ftbl
,quote_ident(f.attname) AS fk
,quote_ident(pf.attname) AS pk
,string_agg(c.conrelid::regclass::text, ', ') AS referencing_tbls
FROM pg_constraint c
JOIN pg_attribute f ON (f.attrelid, f.attnum) = (c.confrelid, c.confkey[1])
LEFT JOIN pg_constraint p ON p.conrelid = c.confrelid AND p.contype = 'p'
LEFT JOIN pg_attribute pf ON (pf.attrelid, pf.attnum)
= (p.conrelid, p.conkey[1])
WHERE c.contype = 'f'
-- AND c.confrelid = 'fk_tbl'::regclass -- only referring this tbl
GROUP BY 1, 2, 3
)
SELECT string_agg(format(
'SELECT %L AS ftbl
, %L AS pk
, %s::text AS pk_val
, %L AS fk
, %L AS referencing_tbls
FROM %1$s WHERE %4$s IS NULL'
, ftbl
, COALESCE(pk, 'NONE')
, COALESCE(pk, 'NULL')
, fk
, referencing_tbls), '
UNION ALL
') || ';'
FROM x;
在整個數據庫中查找所有此類行(注釋了對一個表的限制)。 經過Postgres 9.1.4測試並為我工作。
我將多個引用同一外來列的表分組到一個查詢中,並添加了一個引用表列表以進行概述。
您需要此查詢的聯合:
select *
from ((select 'other_table' as table_name,
other_table_key as primary_key,
'reference_table_key' as table_fk,
ot.reference_table_key
from other_table ot left outer join
reference_table rt
on ot.reference_table_key = rt.reference_table_key
where rt.reference_value is null
) union all
(select 'another_table' as table_name,
another_table_key as primary_key,
'do_stuff_key' as table_fk,
at.do_stuff_key
from another_table at left outer join
reference_table rt
on at.do_stuff_key = rt.reference_table_key
where rt.reference_value is null
)
) t
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.