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

本文涉及的产品
云原生数据库 PolarDB 分布式版,标准版 2核8GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS PostgreSQL Serverless,0.5-4RCU 50GB 3个月
推荐场景:
对影评进行热评分析
简介:
一位网友提到的需求, 在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源码, 看看能不能找到更好的方法.
相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
8月前
|
SQL 关系型数据库 PostgreSQL
把PostgreSQL的表导入SQLite
把PostgreSQL的表导入SQLite
117 0
|
6月前
|
SQL 监控 关系型数据库
实时计算 Flink版操作报错合集之在设置监控PostgreSQL数据库时,将wal_level设置为logical,出现一些表更新和删除操作报错,怎么办
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
|
7月前
|
关系型数据库 PostgreSQL
postgresql如何将没有关联关系的两张表的字段合并
【6月更文挑战第2天】postgresql如何将没有关联关系的两张表的字段合并
164 3
|
7月前
|
SQL 关系型数据库 数据库连接
ClickHouse(20)ClickHouse集成PostgreSQL表引擎详细解析
ClickHouse的PostgreSQL引擎允许直接查询和插入远程PostgreSQL服务器的数据。`CREATE TABLE`语句示例展示了如何定义这样的表,包括服务器信息和权限。查询在只读事务中执行,简单筛选在PostgreSQL端处理,复杂操作在ClickHouse端完成。`INSERT`通过`COPY`命令在PostgreSQL事务中进行。注意,数组类型的处理和Nullable列的行为。示例展示了如何从PostgreSQL到ClickHouse同步数据。一系列的文章详细解释了ClickHouse的各种特性和表引擎。
209 0
|
7月前
|
SQL 关系型数据库 PostgreSQL
【sql】PostgreSQL物化视图表使用案例
【sql】PostgreSQL物化视图表使用案例
70 0
|
8月前
|
关系型数据库 PostgreSQL
postgresql将没有关联关系的两张表合并成一张
【5月更文挑战第4天】postgresql将没有关联关系的两张表合并成一张
266 5
|
7月前
|
关系型数据库 PostgreSQL
postgresql如何将没有关联关系的两张表合并成一张
【6月更文挑战第2天】postgresql如何将没有关联关系的两张表合并成一张
149 0
|
SQL 关系型数据库 数据库
postgresql中连接两张表更新第三张表(updata)
如何结合两张表的数据来更新第三张表
367 0
|
8月前
|
关系型数据库 数据库 PostgreSQL
postgresql | 数据库| 生成2000W条的简单测试表
postgresql | 数据库| 生成2000W条的简单测试表
247 0
|
关系型数据库 PostgreSQL
PostgreSQL表用户列最大个数
PostgreSQL表用户列最大个数
260 0

相关产品

  • 云原生数据库 PolarDB
  • 云数据库 RDS PostgreSQL 版