pg_depend 是 postgresql 中获取真实对象依赖的唯一可靠来源,需严格过滤 classid 和 refclassid 为 'pg_class'::regclass、deptype = 'n'、refobjid >= 16384。

查 pg_depend 是唯一靠谱的起点
PostgreSQL 不像 SQL Server 那样提供开箱即用的 sys.sql_expression_dependencies,也不像 Oracle 有 USER_DEPENDENCIES。所有真实依赖只藏在 pg_depend 里,其他视图(比如 pg_views 或 INFORMATION_SCHEMA.VIEWS)存的只是建视图时的 SQL 快照,表删了、字段重命名了,它们照样显示“存在”。
关键点在于过滤条件必须严格:
-
classid = 'pg_class'::regclass:确保当前对象是视图(objid指向视图 OID) -
refclassid = 'pg_class'::regclass:确保被依赖的是表/视图/物化视图等同类对象(不是函数或类型) -
deptype = 'n':只取 normal 依赖,排除a(auto)、i(internal)、e(extension)等噪音 -
refobjid >= 16384:跳过系统对象(OID
执行时必须带 schema 名和权限校验
pg_get_viewdef() 或 pg_depend 查询失败,90% 是权限或定位问题,不是语法错。
- 视图名必须显式带上 schema,比如
'myschema.myview';不加 schema 默认查public,大小写敏感,引号不能乱加 - 用户需有
USAGE权限在对应 schema 上,且对视图本身有SELECT权限,否则pg_depend查不到记录,pg_get_viewdef()直接返回空或报permission denied - 确认视图存在:
SELECT * FROM pg_views WHERE schemaname = 'myschema' AND viewname = 'myview';
物化视图和外部表要单独处理
pg_depend 不会把物化视图(relkind = 'm')或外部表(relkind = 'f')当普通表链进来——它们的依赖关系不在标准路径上。
- 先查基础依赖:
SELECT DISTINCT refobjid::regclass FROM pg_depend WHERE objid = 'myschema.myview'::regclass AND deptype = 'n' AND refclassid = 'pg_class'::regclass; - 结果里如果出现
matview_name,得去pg_matviews查它的definition字段再展开一层 - 如果出现
foreign_table_name,要去pg_foreign_table找ftserver,再顺到pg_foreign_server和 FDW 配置,它根本没连本地表
别信递归 CONNECT BY,小心循环依赖漏判
有人照搬 Oracle 写法,用 START WITH ... CONNECT BY PRIOR 在 PostgreSQL 里递归查依赖,这会出问题。
-
pg_depend对循环依赖(A → B → A)标记为deptype = 'i'(internal),而不是'n',所以标准deptype = 'n'查询天然漏掉它 - 嵌套视图 + CTE + 子查询里的表,也不会出现在
pg_depend的直接链路上,得靠pg_get_viewdef('myview', true)拿到带 schema 的完整定义,再人工或正则扫FROM和JOIN后的表名 - 若发现某张表在
pg_depend里没出现,但视图执行时报relation "xxx" does not exist,八成是这个原因:建视图时没写 schema 前缀,又碰上search_path变更,解析时找不到
真正难的不是查出第一层依赖,而是确认这些表是否还“活”着、字段有没有被删、物化视图有没有刷新、外部表背后的远程库是否可达——pg_depend 只告诉你“当时建的时候连了谁”,不保证现在还能通。











