一、前言
最近來了個新需求,要求得到數據庫里的視圖是建立在哪些表或視圖上的(以下簡稱視圖的依賴關系)。
對於Oracle和MySql,該需求都較易實現,分別查詢USER_DEPENDENCIES和INFORMATION_SCHEMA.VIEWS、再加些簡單的解析即可。
但對於PostgreSQL就很困難,因為這種依賴關系分散在多個系統表(pg_depend, pg_rewrite)中,且十分不直觀,相關資料也很少。
二、借鑒
經過一番努力,終於度到一篇有價值的帖子:《postgresql/greenplum查詢依賴於表上的視圖》,相應的sql為:
SELECT c.ev_class::regclass::varchar AS objname, pc.oid::regclass::varchar AS refobjname FROM pg_depend a,pg_depend b,pg_class pc,pg_rewrite c WHERE a.refclassid=1259 -- 1259是pg_depend的oid AND a.classid=2618 -- 2618是pg_rewrite的oid AND b.deptype='i' -- 內部依賴 AND a.objid=b.objid AND a.classid=b.classid AND a.refclassid=b.refclassid AND a.refobjid<>b.refobjid AND pc.oid=a.refobjid AND c.oid=b.objid GROUP BY c.ev_class,pc.oid;
已經基本上達到了預期。
三、改進
不過其中的語句的查詢結果是把系統視圖與自建視圖混合在一起了,還需繼續改進。該如何對它們進行區分?
記得以前看過一篇資料,好像說過,非系統對象的OID是從16384(0x4000)開始分配的,於是將其加入查詢條件:
SELECT c.ev_class::regclass::varchar AS objname, pc.oid::regclass::varchar AS refobjname FROM pg_depend a,pg_depend b,pg_class pc,pg_rewrite c WHERE a.refclassid=1259 -- 1259是pg_depend的oid AND a.classid=2618 -- 2618是pg_rewrite的oid AND b.deptype='i' -- 內部依賴 AND a.objid=b.objid AND a.classid=b.classid AND a.refclassid=b.refclassid AND a.refobjid<>b.refobjid AND pc.oid=a.refobjid AND c.oid=b.objid AND (a.objid>=16384 or a.refobjid>=16384) -- 過濾掉系統對象 GROUP BY c.ev_class,pc.oid;
結果符合預期,問題解決。