服务器之家:专注于服务器技术及软件下载分享
分类导航

Mysql|Sql Server|Oracle|Redis|MongoDB|PostgreSQL|Sqlite|DB2|mariadb|Access|数据库技术|

服务器之家 - 数据库 - PostgreSQL - PostgreSQL 查看表的主外键等约束关系详解

PostgreSQL 查看表的主外键等约束关系详解

2021-04-05 20:51雨临Lewis PostgreSQL

这篇文章主要介绍了PostgreSQL 查看表的主外键等约束关系详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

我就废话不多说了,大家还是直接看代码吧~

?
1
2
3
4
5
6
7
8
9
10
SELECT
   tc.constraint_name, tc.table_name, kcu.column_name,
   ccu.table_name AS foreign_table_name,
   ccu.column_name AS foreign_column_name,
   tc.is_deferrable,tc.initially_deferred
 FROM
   information_schema.table_constraints AS tc
   JOIN information_schema.key_column_usage AS kcu ON tc.constraint_name = kcu.constraint_name
   JOIN information_schema.constraint_column_usage AS ccu ON ccu.constraint_name = tc.constraint_name
 WHERE constraint_type = 'FOREIGN KEY' AND tc.table_name = 'your table name';

constraint_type有四种:

?
1
UNIQUEPRIMARY KEYCHECKFOREIGN KEY

通过修改上边sql语句的table_name和constraint_type来进行相应的查询

补充:PostgreSQL查询约束和创建删除约束

查询约束constraint

?
1
2
3
4
5
6
7
8
9
10
SELECT
   tc.constraint_name, tc.table_name, kcu.column_name,
   ccu.table_name AS foreign_table_name,
   ccu.column_name AS foreign_column_name,
   tc.is_deferrable,tc.initially_deferred
 FROM
   information_schema.table_constraints AS tc
   JOIN information_schema.key_column_usage AS kcu ON tc.constraint_name = kcu.constraint_name
   JOIN information_schema.constraint_column_usage AS ccu ON ccu.constraint_name = tc.constraint_name
 WHERE constraint_type = 'UNIQUE' AND tc.table_name = 'table_name';

constraint_type有四种:

UNIQUE、PRIMARY KEY、CHECK、FOREIGN KEY, 通过修改上边sql语句的table_name和constraint_type来进行相应的查询。

添加约束

?
1
ALTER TABLE table_name ADD CONSTRAINT uk_users_name1 UNIQUE (NAME);

删除约束

?
1
alter table table_name drop constraint if EXISTS uk_users_name1;

补充:PostgreSQL的依赖约束(系统表pg_depend和pg_constraint)详解

pg_depend是postgres的一张系统表,用来记录数据库对象之间的依赖关系,除了常见的主外键,还有其他一些内部依赖关系,可以通过这个系统表呈现出来。

一、表结构:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
postgres=# \d pg_constraint
   Table "pg_catalog.pg_constraint"
  Column   |   Type   | Modifiers
---------------+--------------+-----------
 conname    | name     | not null    -- 约束名
 connamespace | oid     | not null    -- 约束所在命名空间的OID
 contype    | "char"    | not null    -- 约束类型
 condeferrable | boolean   | not null    -- 约束是否可以推迟
 condeferred  | boolean   | not null    -- 缺省情况下,约束是否可以推迟
 convalidated | boolean   | not null    -- 约束是否经过验证
 conrelid   | oid     | not null    -- 约束所在的表的OID
 contypid   | oid     | not null    -- 约束所在的域的OID
 conindid   | oid     | not null    -- 如果是唯一、主键、外键或排除约束,则为支持这个约束的索引;否则为0
 confrelid   | oid     | not null    -- 如果是外键,则为参考的表;否则为 0
 confupdtype  | "char"    | not null    -- 外键更新操作代码
 confdeltype  | "char"    | not null    -- 外键删除操作代码
 confmatchtype | "char"    | not null    -- 外键匹配类型
 conislocal  | boolean   | not null   
 coninhcount  | integer   | not null    -- 约束直接继承祖先的数量
 connoinherit | boolean   | not null   
 conkey    | smallint[]  |     -- 如果是表约束(包含外键,但是不包含约束触发器),则是约束字段的列表
 confkey    | smallint[]  |     -- 如果是一个外键,是参考的字段的列表
 conpfeqop   | oid[]    |     -- 如果是一个外键,是PK = FK比较的相等操作符的列表
 conppeqop   | oid[]    |    -- 如果是一个外键,是PK = PK比较的相等操作符的列表
 conffeqop   | oid[]    |     -- 如果是一个外键,是FK = FK比较的相等操作符的列表
 conexclop   | oid[]    |     -- 如果是一个排除约束,是每个字段排除操作符的列表
 conbin    | pg_node_tree |     -- 如果是一个检查约束,那就是其表达式的内部形式
 consrc    | text     |     -- 如果是检查约束,则是表达式的人类可读形式
Indexes:
  "pg_constraint_oid_index" UNIQUE, btree (oid)
  "pg_constraint_conname_nsp_index" btree (conname, connamespace)
  "pg_constraint_conrelid_index" btree (conrelid)
  "pg_constraint_contypid_index" btree (contypid)

pg_depend.deptype字段类型9.1之后多了一个extension的类型,目前类型有

?
1
2
3
4
5
DEPENDENCY_NORMAL (n)   :普通的依赖对象,如表与schema的关系
DEPENDENCY_AUTO (a)    :自动的依赖对象,如主键约束
DEPENDENCY_INTERNAL (i)  :内部的依赖对象,通常是对象本身
DEPENDENCY_EXTENSION (e) :9.1新增的的扩展依赖
DEPENDENCY_PIN (p)    :系统内置的依赖

二、例子

wiki上有一个SQL可以列出系统和用户对象的各种依赖关系,低版本的可以看wiki上的另一个写法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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

?
1
2
3
4
5
6
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上面的

加一个主键约束

?
1
2
3
4
5
6
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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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.删除该表所有的系统依赖信息 上面的问题需要删除

?
1
2
3
4
postgres=# delete from pg_depend where objid = 16469 or refobjid = 16469 ;
DELETE 2
postgres=# drop table tbl_parent;
DROP TABLE

3.要说一点的是不要去手工删除一些系统表信息来达到删除约束的目的,容易因删不干净而造成各种异常

以上为个人经验,希望能给大家一个参考,也希望大家多多支持服务器之家。如有错误或未考虑完全的地方,望不吝赐教。

原文链接:https://lewky.blog.csdn.net/article/details/78922018

延伸 · 阅读

精彩推荐
  • PostgreSQL分布式 PostgreSQL之Citus 架构

    分布式 PostgreSQL之Citus 架构

    节点 Citus 是一种 PostgreSQL 扩展,它允许数据库服务器(称为节点)在“无共享(shared nothing)”架构中相互协调。这些节点形成一个集群,允许 PostgreSQL 保存比单...

    未知802023-05-07
  • PostgreSQLpostgresql 中的to_char()常用操作

    postgresql 中的to_char()常用操作

    这篇文章主要介绍了postgresql 中的to_char()常用操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    J符离13432021-04-12
  • PostgreSQLPostgresql开启远程访问的步骤全纪录

    Postgresql开启远程访问的步骤全纪录

    postgre一般默认为本地连接,不支持远程访问,所以如果要开启远程访问,需要更改安装文件的配置。下面这篇文章主要给大家介绍了关于Postgresql开启远程...

    我勒个去6812020-04-30
  • PostgreSQLPostgresql查询效率计算初探

    Postgresql查询效率计算初探

    这篇文章主要给大家介绍了关于Postgresql查询效率计算的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Postgresql具有一定的参考学习价...

    轨迹4622020-05-03
  • PostgreSQLRDS PostgreSQL一键大版本升级技术解密

    RDS PostgreSQL一键大版本升级技术解密

    一、PostgreSQL行业位置 (一)行业位置 在讨论PostgreSQL(下面简称为PG)在整个数据库行业的位置之前,我们先看一下阿里云数据库在全球的数据库行业里的...

    未知1192023-05-07
  • PostgreSQL深入理解PostgreSQL的MVCC并发处理方式

    深入理解PostgreSQL的MVCC并发处理方式

    这篇文章主要介绍了深入理解PostgreSQL的MVCC并发处理方式,文中同时介绍了MVCC的缺点,需要的朋友可以参考下 ...

    PostgreSQL教程网3622020-04-25
  • PostgreSQLpostgresql 数据库中的数据转换

    postgresql 数据库中的数据转换

    postgres8.3以后,字段数据之间的默认转换取消了。如果需要进行数据变换的话,在postgresql数据库中,我们可以用"::"来进行字段数据的类型转换。...

    postgresql教程网12482021-10-08
  • PostgreSQLPostgreSQL标准建表语句分享

    PostgreSQL标准建表语句分享

    这篇文章主要介绍了PostgreSQL标准建表语句分享,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    码上得天下7962021-02-27