PostgreSQL 如何比较两个表的定义是否一致

一位网友提到的需求, 在PostgreSQL中如何比对两个表的定义差异.
如果只比对字段类型, 不比对约束, 触发器, 策略, 权限等其他属性的话, 只需要使用pg_attribute这个catalog即可.
例子 : 
创建两个测试表, 
postgres=# create table tbl1 (id int, info text, c1 numeric(10,3), c2 timestamp without time zone);
CREATE TABLE
postgres=# create table tbl2 (id int, info text, c0 int, c00 int, c1 numeric(10,3), c2 timestamp with time zone);
CREATE TABLE

postgres=# alter table tbl2 drop column c00;
ALTER TABLE

postgres=# alter table tbl2 add column c00 int;
ALTER TABLE
postgres=# alter table tbl2 add column c01 int;
ALTER TABLE

当前结构
postgres=# \d tbl1
               Table "public.tbl1"
 Column |            Type             | Modifiers 
--------+-----------------------------+-----------
 id     | integer                     | 
 info   | text                        | 
 c1     | numeric(10,3)               | 
 c2     | timestamp without time zone | 

postgres=# \d tbl2
              Table "public.tbl2"
 Column |           Type           | Modifiers 
--------+--------------------------+-----------
 id     | integer                  | 
 info   | text                     | 
 c0     | integer                  | 
 c1     | numeric(10,3)            | 
 c2     | timestamp with time zone | 
 c00    | integer                  | 
 c01    | integer                  | 

使用这个catalog
postgres=# \d pg_attribute
    Table "pg_catalog.pg_attribute"
    Column     |   Type    | Modifiers 
---------------+-----------+-----------
 attrelid      | oid       | not null
 attname       | name      | not null
 atttypid      | oid       | not null
 attstattarget | integer   | not null
 attlen        | smallint  | not null
 attnum        | smallint  | not null
 attndims      | integer   | not null
 attcacheoff   | integer   | not null
 atttypmod     | integer   | not null
 attbyval      | boolean   | not null
 attstorage    | "char"    | not null
 attalign      | "char"    | not null
 attnotnull    | boolean   | not null
 atthasdef     | boolean   | not null
 attisdropped  | boolean   | not null
 attislocal    | boolean   | not null
 attinhcount   | integer   | not null
 attcollation  | oid       | not null
 attacl        | aclitem[] | 
 attoptions    | text[]    | 
 attfdwoptions | text[]    | 
Indexes:
    "pg_attribute_relid_attnam_index" UNIQUE, btree (attrelid, attname)
    "pg_attribute_relid_attnum_index" UNIQUE, btree (attrelid, attnum)

当前两个表在pg_attribute中的数据如下, 系统隐含列和已删除的列排除掉
postgres=# select attrelid,attname,atttypid,attlen,atttypmod from pg_attribute where attrelid='tbl2'::regclass and attnum>=1 and not attisdropped;
 attrelid | attname | atttypid | attlen | atttypmod 
----------+---------+----------+--------+-----------
    24681 | id      |       23 |      4 |        -1
    24681 | info    |       25 |     -1 |        -1
    24681 | c0      |       23 |      4 |        -1
    24681 | c1      |     1700 |     -1 |    655367
    24681 | c2      |     1184 |      8 |        -1
    24681 | c00     |       23 |      4 |        -1
    24681 | c01     |       23 |      4 |        -1
(7 rows)

postgres=# select attrelid,attname,atttypid,attlen,atttypmod from pg_attribute where attrelid='tbl1'::regclass and attnum>=1 and not attisdropped;
 attrelid | attname | atttypid | attlen | atttypmod 
----------+---------+----------+--------+-----------
    24675 | id      |       23 |      4 |        -1
    24675 | info    |       25 |     -1 |        -1
    24675 | c1      |     1700 |     -1 |    655367
    24675 | c2      |     1114 |      8 |        -1
(4 rows)

使用这个SQL就可以比对两个表不同的字段
with 
t1 as (
select attrelid,attname,attlen,format_type(atttypid,atttypmod) as typ from pg_attribute where attrelid='tbl1'::regclass and attnum>=1 and not attisdropped
),
t2 as (
select attrelid,attname,attlen,format_type(atttypid,atttypmod) as typ from pg_attribute where attrelid='tbl2'::regclass and attnum>=1 and not attisdropped
)
select t1.*,t2.* from t1 full outer join t2 on (t1.attname = t2.attname and t1.typ=t2.typ and t1.attlen=t2.attlen) where t1.* is null or t2.* is null;

 attrelid | attname | atttypid | attlen | atttypmod | attrelid | attname | atttypid | attlen | atttypmod 
----------+---------+----------+--------+-----------+----------+---------+----------+--------+-----------
    24675 | c2      |     1114 |      8 |        -1 |          |         |          |        |          
          |         |          |        |           |    24681 | c01     |       23 |      4 |        -1
          |         |          |        |           |    24681 | c00     |       23 |      4 |        -1
          |         |          |        |           |    24681 | c0      |       23 |      4 |        -1
          |         |          |        |           |    24681 | c2      |     1184 |      8 |        -1
(5 rows)

长度不同也可以比对出来
postgres=# alter table tbl1 add column n1 numeric(10,2);
ALTER TABLE
postgres=# alter table tbl2 add column n1 numeric(10,3);
ALTER TABLE

使用format_type格式化一下类型, 更友好的输出
postgres=# with                                         
t1 as (
select attrelid,attname,attlen,format_type(atttypid,atttypmod) as typ from pg_attribute where attrelid='tbl1'::regclass and attnum>=1 and not attisdropped
),
t2 as (
select attrelid,attname,attlen,format_type(atttypid,atttypmod) as typ from pg_attribute where attrelid='tbl2'::regclass and attnum>=1 and not attisdropped
)
select t1.*,t2.* from t1 full outer join t2 on (t1.attname = t2.attname and t1.typ=t2.typ and t1.attlen=t2.attlen) where t1.* is null or t2.* is null;
 attrelid | attname | attlen |             typ             | attrelid | attname | attlen |           typ            
----------+---------+--------+-----------------------------+----------+---------+--------+--------------------------
    24675 | c2      |      8 | timestamp without time zone |          |         |        | 
    24675 | n1      |     -1 | numeric(10,2)               |          |         |        | 
          |         |        |                             |    24681 | c0      |      4 | integer
          |         |        |                             |    24681 | n1      |     -1 | numeric(10,3)
          |         |        |                             |    24681 | c00     |      4 | integer
          |         |        |                             |    24681 | c01     |      4 | integer
          |         |        |                             |    24681 | c2      |      8 | timestamp with time zone
(7 rows)

如果你还需要比对其他的不同之处, 例如约束, 字段顺序, 触发器等, 建议用pg_dump将两个表的定义导出, 然后diff一下.
或者研究一下pg_dump源码, 看看能不能找到更好的方法.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PostgreSQL是以加州大学伯克利分校计算机系开发的POSTGRES,现在已经更名为PostgreSQL. PostgreSQL支持大部分SQL标准并且提供了许多其它现代特性:复杂查询、外键、触发器、视图、事务完整性等。 PostgreSQL 是一个免费的对象-关系数据库服务器(数据库管理系统),它在灵活的 BSD-风格许可证下发行。它提供了相对其他开放源代码数据库系统(比如 MySQL 和 Firebird),和专有系统(比如 Oracle、Sybase、IBM 的 DB2 和 Microsoft SQL Server)之外的另一种选择。 事实上, PostgreSQL 的特性覆盖了 SQL-2/SQL-92 和 SQL-3/SQL-99,首先,它包括了可以说是目前世界上最丰富的数据类型的支持,其有些数据类型可以说连商业数据库都不具备, 比如 IP 类型和几何类型等;其次,PostgreSQL 是全功能的自由软件数据库,很长时间以来,PostgreSQL 是唯一支持事务、子查询、多版本并行控制系统(MVCC)、数据完整性检查等特性的唯一的一种自由软件的数据库管理系统。 Inprise 的 InterBase 以及SAP等厂商将其原先专有软件开放为自由软件之后才打破了这个唯一。最后,PostgreSQL拥有一支非常活跃的开发队伍,而且在许多黑客的努力下,PostgreSQL 的质量日益提高。从技术角度来讲,PostgreSQL 采用的是比较经典的C/S(client/server)结构,也就是一个客户端对应一个服务器端守护进程的模式,这个守护进程分析客户端来的查询请求,生成规划树,进行数据检索并最终把结果格式化输出后返回给客户端。为了便于客户端的程序的编写,由数据库服务器提供了统一的客户端 C 接口。而不同的客户端接口都是源自这个 C 接口,比如ODBC,JDBC,Python,Perl,Tcl,C/C++,ESQL等, 同时也要指出的是,PostgreSQL 对接口的支持也是非常丰富的,几乎支持所有类型的数据库客户端接口。这一点也可以说是 PostgreSQL 一大优点。 本课程作为PostgreSQL数据库管理之三,主要讲解以下内容:1.     PostgreSQL约束讲解和剖析2.     PostgreSQL数据类型3.     PostgreSQL的结构管理4.     PostgreSQL条件达式和操作5.     PostgreSQL使用小技巧
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值