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

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

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有四种:

UNIQUE、PRIMARY KEY、CHECK、FOREIGN KEY

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

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

查询约束constraint

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来进行相应的查询。

添加约束

ALTER TABLE table_name ADD CONSTRAINT uk_users_name1 UNIQUE (NAME);

删除约束

alter table table_name drop constraint if EXISTS uk_users_name1;

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

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

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的类型,目前类型有

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

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

(0)

相关推荐

  • postgresql 计算两点距离的2种方法小结

    postgresql计算两点距离 下面两种方法: select ST_Distance( ST_SetSRID(ST_MakePoint(115.97166453999147,28.716493914230423),4326)::geography, ST_SetSRID(ST_MakePoint(106.00231199774656,29.719258550486572),4326)::geography ), ST_Length( ST_MakeLine( ST_MakePoint(115.

  • Postgresql 动态统计某一列的某一值出现的次数实例

    实例解析: select to_char(log.date, 'yyyy-MM-dd HH24') as hour, log.exten, sum(case log.grade when '1' then 1 else 0 end) as "1", sum(case log.grade when '2' then 1 else 0 end) as "2", sum(case log.grade when '3' then 1 else 0 end) as "

  • postgresql 计算距离的实例(单位直接生成米)

    之前用的是ST_Distance 函数,但是貌似需要进行一次单位的转换,而且网上有说那种转换不是特别准确,现在暂时将该算法记录在此: select st_distance(ST_GeomFromText('POINT(120.451737 36.520975)',900913),ST_GeomFromText('POINT(120.455636 36.520885)',900913))*60*1.852; 这里的计算方式倒是可以换坐标系,但是,测试了两个坐标系都没有起作用.而且该种方式转换过单位

  • PostgreSQL 更新视图脚本的注意事项说明

    项目最早是基于Oracle的,移植到PostgreSQL后,本着尽量少修改的原则,创建/更新视图的脚本也沿用了Oracle风格的CREATE OR REPLACE VIEW形式.但是每当要更新视图定义时,常常报"cannot change name of view column xxx to yyy"的错误,通常是在视图修改某字段名.中间增加字段.删除字段时发生. 究其原因,是PostgreSQL虽然支持CREATE OR REPLACE VIEW语义,却有着容易让人忽略的重要限制(O

  • PostgreSQL中enable、disable和validate外键约束的实例

    我就废话不多说了,大家还是直接看实例吧~ postgres=# create table t1(a int primary key,b text,c date); CREATE TABLE postgres=# create table t2(a int primary key,b int references t1(a),c text); CREATE TABLE postgres=# insert into t1 (a,b,c) values(1,'aa',now()); INSERT 0

  • postgreSQL中的row_number() 与distinct用法说明

    我就废话不多说了,大家还是直接看代码吧~ select count(s.*) from ( select *, row_number() over (partition by fee_date order by fee_date) as gr from new_order where news_id='novel' and order_status='2' ) s where s.gr = 1 SELECT count(DISTINCT fee_date) as dis from new_ord

  • PostgreSQL 修改视图的操作

    最近发现PostgreSQL(create or replace) 修改视图有很多的限制,不像SQL Server和Oracle那样可以随意修改. 错误提示 修改视图原有字段 ERROR: cannot change name of view column "user_id" to "?column?" 删除视图原有字段 ERROR: cannot drop columns from view 找到如下原因,内容原文 究其原因,是PostgreSQL虽然支持CREA

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

    我就废话不多说了,大家还是直接看代码吧~ 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

  • MySQL外键使用及说明详解

    一.外键约束 MySQL通过外键约束来保证表与表之间的数据的完整性和准确性. 外键的使用条件: 1.两个表必须是InnoDB表,MyISAM表暂时不支持外键(据说以后的版本有可能支持,但至少目前不支持): 2.外键列必须建立了索引,MySQL 4.1.2以后的版本在建立外键时会自动创建索引,但如果在较早的版本则需要显示建立: 3.外键关系的两个表的列必须是数据类型相似,也就是可以相互转换类型的列,比如int和tinyint可以,而int和char则不可以: 外键的好处: 可以使得两张表关联,保证

  • 探讨SQL利用INFORMATION_SCHEMA系统视图如何获取表的主外键信息

    接着上篇文章<解析SQL 表结构信息查询 含主外键.自增长>里面提到了INFORMATION_SCHEMA视图,其实到了SQL 2005微软都主推大家使用INFORMATION_SCHEMA系统视图,而不是在使用sys东东了,当然目前还是有许多信息只能通过sys视图来查询.这里我们还是以查询表结果信息为例来说明一些主要的INFORMATION_SCHEMA视图的使用.首先我们需要查询列的信息,这需要用到[INFORMATION_SCHEMA].[COLUMNS]系统视图来查询数据列的信息,SQ

  • 深入mysql外键关联问题的详解

    今儿继续再看老师给推荐的深入浅出mysql数据库开发这本书,看到innodb数据库的外键关联问题时,遇到了一个问题,书上写的是可以对父表进行修改,从而同步到子表的外键上去,可是自己的实验却是没有能够. 复制代码 代码如下: mysql> show create table country\G*************************** 1. row ***************************       Table: countryCreate Table: CREATE

  • Django 外键的使用方法详解

    一.描述 在利用django做网络开发的时候我们会遇到一个问题就是,我们建立了多张数据表,但是多张数据表中的内容是不一样的,但是之间有着联系比如: 我有两张表,一张是记录歌曲信息的内容,一张是对歌曲操作的内容(下载次数浏览次数),如果我在views中对下载次数进行一个排序,但是我不能只显示下载次数,我需要歌名的内容,此时我们就需要外键来完成这个工作. 歌曲的操作次数 歌曲信息 二.解决 由于在django中都是使用models.py文件来管理数据库,再通过views.py进行连接操作,最后用ur

  • MySQL创建数据表并建立主外键关系详解

    前言 为mysql数据表建立主外键需要注意以下几点: 需要建立主外键关系的两个表的存储引擎必须是InnoDB. 外键列和参照列必须具有相似的数据类型,即可以隐式转换的数据类型. 外键列和参照列必须创建索引,如果外键列不存在索引,mysql将自动创建索引. 一.SQL语句创建数据表并设置主外键关系 create table demo.ChineseCharInfo ( ID int not null auto_increment, Hanzi varchar(10) not null, prima

  • MySQL多表操作的外键约束教程

    目录 一.多表关系 一对一关系 一对多/多对一关系 多对多关系 二.外键约束 特点 创建外键约束 方式1-在创建表时设置外键约束 方式2-在创建表时设置外键约束 在外键约束下的操作 1.数据插入 2.删除数据 3.删除外键约束 外键约束-多对多关系 操作 一.多表关系 MySQL多表之间的关系可以概括为:一对一.一对多/多对一关系,多对多 一对一关系 一个学生只有一张身份证;一张身份证只能对应一学生.在任一表中添加唯─外键,指向另一方主键,确保一对一关系.一般一对一关系很少见,遇到一对一关系的表

  • postgresql查看表和索引的情况,判断是否膨胀的操作

    索引膨胀的几个来源: 1 大量删除发生后,导致索引页面稀疏,降低了索引使用效率. 2 PostgresQL 9.0之前的版本,vacuum full 会同样导致索引页面稀疏. 3 长时间运行的事务,禁止vacuum对表的清理工作,因而导致页面稀疏状态一直保持. 查看重复索引 SELECT pg_size_pretty(SUM(pg_relation_size(idx))::BIGINT) AS SIZE, (array_agg(idx))[1] AS idx1, (array_agg(idx))

  • jpa使用注解生成表时无外键问题及解决

    目录 jpa注解生成表时无外键 使用jpa自动建表不生成外键情况 情况1 情况2 jpa注解生成表时无外键 刚入手springboot时,在使用jpa实体注解生成表无外键.是因为jpa不知道使用何种Dialect创建,默认没有外键. 在配置文件加上 database-platform: org.hibernate.dialect.MySQL5InnoDBDialect 就好了. 使用jpa自动建表不生成外键情况 springboot项目搭配的jpa使用时候,有一对多的关系注解,那么自动会生成外键

  • MariaDB数据库的外键约束实例详解

    外键 外键的用途是确保数据的完整性.它通常包括以下几种: 1 实体完整性,确保每个实体是唯一的(通过主键来实施) 2 域完整性,确保属性值只从一套特定可选的集合里选择 3 关联完整性,确保每个外键或是NULL(如果允许的话)或含有与相关主键值相配的值 1.什么是外键约束 与主键约束不同,创建外键约束不会自动创建对应的索引. 但是由于以下原因,对外键手动创建索引通常是有用的: 当在查询中组合相关表中的数据时,经常在联接条件中使用外键列,方法是将一个表的外键约束中的一列或多列与另一个表中的主键列或唯

随机推荐