pg_depend是postgres的一张系统表,用来记录数据库对象之间的依赖关系,除了常见的主外键,还有其他一些内部依赖关系,可以通过这个系统表呈现出来。
一、表结构:
postgres=# \d+ pg_depend
Table "pg_catalog.pg_depend"
Column | Type | Modifiers | Storage | Stats target | Description
-------------+---------+-----------+---------+--------------+-------------
classid | oid | not null | plain | | 系统OID
objid | oid | not null | plain | | 对象OID
objsubid | integer | not null | plain | |
refclassid | oid | not null | plain | | 引用系统OID
refobjid | oid | not null | plain | | 引用对象ID
refobjsubid | integer | not null | plain | |
deptype | "char" | not null | plain | | pg_depend类型
Indexes:
"pg_depend_depender_index" btree (classid, objid, objsubid)
"pg_depend_reference_index" btree (refclassid, refobjid, refobjsubid)
Has OIDs: no
--BTW:OID是Object Identifier的缩写,是对象ID的意思,因为是无符号的4字节类型,不够足够大,所以一般不用来做主键使用,仅系统内部,比如系统表等应用,可以与一些整型数字进行转换。与之相关的系统参数是default_with_oids,默认是off
pg_depend.deptype字段类型9.1之后多了一个extension的类型,目前类型有
DEPENDENCY_NORMAL (n) :普通的依赖对象,如表与schema的关系
DEPENDENCY_AUTO (a) :自动的依赖对象,如主键约束
DEPENDENCY_INTERNAL (i) :内部的依赖对象,通常是对象本身
DEPENDENCY_EXTENSION (e) :9.1新增的的扩展依赖
DEPENDENCY_PIN (p) :系统内置的依赖
二、例子
wiki上有一个SQL可以列出系统和用户对象的各种依赖关系,低版本的可以看wiki上的另一个写法
SELECT classid::regclass AS "depender object class",
CASE classid
WHEN 'pg_class'::regclass THEN objid::regclass::text
WHEN 'pg_type'::regclass THEN objid::regtype::text
WHEN 'pg_proc'::regclass THEN objid::regprocedure::text
ELSE objid::text
END AS "depender object identity",
objsubid,
refclassid::regclass AS "referenced object class",
CASE refclassid
WHEN 'pg_class'::regclass THEN refobjid::regclass::text
WHEN 'pg_type'::regclass THEN refobjid::regtype::text
WHEN 'pg_proc'::regclass THEN refobjid::regprocedure::text
ELSE refobjid::text
END AS "referenced object identity",
refobjsubid,
CASE deptype
WHEN 'p' THEN 'pinned'
WHEN 'i' THEN 'internal'
WHEN 'a' THEN 'automatic'
WHEN 'n' THEN 'normal'
END AS "dependency type"
FROM pg_catalog.pg_depend WHERE (objid >= 16384 OR refobjid >= 16384);
BTW:我通常喜欢在where后面加个条件 and deptype <>'i' 排除internal依赖
建一张普通的表,执行上面的SQL
postgres=# create table tbl_parent(id int);
CREATE TABLE
postgres=# 执行上面的SQL;
depender object class | depender object identity | objsubid | referenced object class | referenced object identity | refobjsubid | dependency type
-----------------------+--------------------------+----------+-------------------------+------------- pg_class | tbl_parent | 0 | pg_namespace | 2200 | 0 | normal
(1 row)
--普通用户来看只是建了个表,但是没有约束,其实因为这个表是建立在schema下面,表是依赖于schema上面的
加一个主键约束
postgres=# alter table tbl_parent add primary key(id);
ALTER TABLE
depender object class | depender object identity | objsubid | referenced object class | referenced object identity | refobjsubid | dependency type
-----------------------+--------------------------+----------+-------------------------+------- pg_class | tbl_parent | 0 | pg_namespace | 2200 | 0 | normal
pg_constraint | 16469 | 0 | pg_class | tbl_parent | 1 | automatic
(2 rows)
--多了一个约束的信息,下面的这条信息表明这个主键约束是依赖于表上的,并且是自动模式,详细信息可以在系统表pg_constrant里面查询
三、非正常删除
正常情况下用户删除有依赖关系的对象时会提示需要先删除最里层没依赖的对象,但是如果通过删除系统表,但又删得不对,就会导致异常,比如上面这个例子会出现
cache lookup failed for constraint
postgres=# select oid,conname,connamespace,contype from pg_constraint where conname like 'tbl_parent%';
oid | conname | connamespace | contype
-------+-----------------+--------------+---------
16469 | tbl_parent_pkey | 2200 | p
(1 row)
postgres=# delete from pg_constraint where conname like 'tbl_parent%';
DELETE 1
postgres=# select oid,conname,connamespace,contype from pg_constraint where conname like 'tbl_parent%';
oid | conname | connamespace | contype
-----+---------+--------------+---------
(0 rows)
postgres=# drop table tbl_parent;
ERROR: cache lookup failed for constraint 16469 --16496是约束的OID
postgres=#
--出现这个问题,是因为手工把约束对象删除了,但是在pg_depend依赖关系里面却仍然存在关系,所以删除该表时发现最里层的依赖对象找不到了就报错了,
解决:
1.手工恢复该表的约束对象,比较难也比较烦
2.删除该表所有的系统依赖信息 上面的问题需要删除
postgres=# delete from pg_depend where objid = 16469 or refobjid = 16469 ;
DELETE 2
postgres=# drop table tbl_parent;
DROP TABLE
3.要说一点的是不要去手工删除一些系统表信息来达到删除约束的目的,容易因删不干净而造成各种异常
参考: http://wiki.postgresql.org/wiki/Pg_depend_display