写了个命令版的表结构差异对比工具(仅限于 MariaDB) - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
KURANADO
V2EX    分享创造

写了个命令版的表结构差异对比工具(仅限于 MariaDB)

  •  
  •   KURANADO 218 天前 1382 次点击
    这是一个创建于 218 天前的主题,其中的信息可能已经有所发展或是发生改变。

    项目上不同环境发版需要对比表结构差异,为此经常需要手动点击 Navicat 的表结构同步功能进行数据库比对,生成 create table 、drop table 、alter table 等语句

    为了自动化比对,封装了一个命令行版的对比工具,在 shell 脚本中调用,一键输出同步语句。

    例如初始情况下 a_chemab_schema 均有如下 ddl:

    create table user ( id bigint comment '主键', name varchar(30) null comment '姓名', address varchar(50) null comment '地址', number varchar(20) null comment '编号', height float null comment '身高' ); create table teacher ( name varchar(30) null comment '姓名' ); create index idx_name on user(name); create index idx_multiple_field on user(name, address); create table course ( id bigint primary key auto_increment comment '主键', name varchar(30) null comment '课程名称', teacher varchar(30) null comment '教师', credit float null comment '学分' ); create table pig ( id bigint not null comment '名称', weight bigint not null comment '重量' ); 

    此时对 a_schema 做如下修改:

    use a_schema; alter table user modify column id bigint primary key auto_increment not null comment '主键'; alter table user add column age int default 18 null comment '年龄'; alter table user add column create_time datetime not null default current_timestamp comment '创建时间'; alter table user modify column address varchar(100) not null default 'Shanghai' comment '地址'; alter table user change column number phone varchar(20) null comment '电话号码'; alter table user drop column height; alter table user add unique index uk_phone(phone); alter table user drop index idx_name; create table student( id bigint primary key auto_increment comment '主键', no varchar(30) null comment '学号', name varchar(30) null comment '姓名' ); create unique index uk_no on student(no); drop index idx_multiple_field on user; create index idx_multiple_field on user(name, phone); drop table course; alter table user add unique index uk_test(age, create_time); alter table student add index idx_name(name); alter table teacher add COLUMN `id` bigint NOT NULL primary key AUTO_INCREMENT COMMENT '主键' FIRST; alter table pig add unique index uk_id_weight(id, weight); alter table pig modify column id bigint not null primary key auto_increment comment '名称'; 

    执行命令将会对比表结构差异后输出同步语句:

    $ ddl-diff \ --original-user root \ --original-password 123456 \ --original-host 127.0.0.1 \ --original-schema a_schema \ --target-user root \ --target-password 123456 \ --target-host 127.0.0.1 \ --target-schema b_schema 
    use b_schema; CREATE TABLE `student`( `id` bigint(20) NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '主键', `no` varchar(30) NULL DEFAULT NULL COMMENT '学号', `name` varchar(30) NULL DEFAULT NULL COMMENT '姓名', INDEX `idx_name` (`name`) USING BTREE, UNIQUE INDEX `uk_no` (`no`) USING BTREE); ALTER TABLE `user` DROP INDEX `idx_name`; ALTER TABLE `user` DROP INDEX `idx_multiple_field`; ALTER TABLE `user` ADD COLUMN `phone` varchar(20) NULL DEFAULT NULL COMMENT '电话号码' AFTER `address`; ALTER TABLE `user` ADD COLUMN `age` int(11) NULL DEFAULT 18 COMMENT '年龄' AFTER `phone`; ALTER TABLE `user` ADD COLUMN `create_time` datetime NOT NULL DEFAULT current_timestamp() COMMENT '创建时间' AFTER `age`; ALTER TABLE `user` MODIFY COLUMN `id` bigint(20) NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '主键' FIRST; ALTER TABLE `user` MODIFY COLUMN `address` varchar(100) NOT NULL DEFAULT 'Shanghai' COMMENT '地址' AFTER `name`; ALTER TABLE `user` DROP COLUMN `height`; ALTER TABLE `user` DROP COLUMN `number`; ALTER TABLE `user` ADD INDEX `idx_multiple_field` (`name`,`phone`) USING BTREE; ALTER TABLE `user` ADD UNIQUE INDEX `uk_test` (`age`,`create_time`) USING BTREE; ALTER TABLE `user` ADD UNIQUE INDEX `uk_phone` (`phone`) USING BTREE; ALTER TABLE `pig` MODIFY COLUMN `id` bigint(20) NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '名称' FIRST; ALTER TABLE `pig` ADD UNIQUE INDEX `uk_id_weight` (`id`,`weight`) USING BTREE; ALTER TABLE `teacher` ADD COLUMN `id` bigint(20) NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '主键' FIRST; DROP TABLE IF EXISTS `course`; 

    目前存在的缺点有:

    • 如果使用的是 MySQL 数据库,则无法正确区分 default 表达式中的普通字符串和 MySQL 内置函数(问题原因是 MySQL INFORMATION_SCHEMA.COLUMNS 中并未对字符串和函数做区分。一种解决方法是通过将 SHOW CREATE TABLE xxx 的返回结果解析成 AST ,sqlparser crate 就具有这种解析能力); MariaDB 无此问题。
    • 无法区分字段重命名的情况,只能输出先删除字段、后新增字段的 alter table 语句。这是因为 INFORMATION_SCHEMA.COLUMNS 没有存储字段 id 。Navicat 、DataGrip 等工具的表结构差异对比都有此问题,所以在执行返回的语句之前,请务必仔细确认之后再执行。如果有小伙伴知道如何解决该问题,欢迎跟帖讨论。

    源码地址:https://github.com/KURANADO2/ddl-diff

    2 条回复    2025-03-07 18:40:03 +08:00
    jybox
        1
    jybox  
       218 天前
    之前用过这个工具 https://www.skeema.io
    很适合在几个环境之间同步表结构
    KURANADO
        2
    KURANADO  
    OP
       218 天前
    @jybox 好东西
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2586 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 23ms UTC 04:53 PVG 12:53 LAX 21:53 JFK 00:53
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86