mysql—声明性地将sql模式应用于表的最简单方法?

pgky5nke  于 2021-07-29  发布在  Java
关注(0)|答案(1)|浏览(328)

目标:我正在寻找一种声明性和可重复的方式,将sql表模式“应用”到数据库中

我试过的

下面是一个sql脚本,它实现了我想要的功能(从我对mysql的肤浅知识和一些手动测试可以看出这是最好的):
如果表不存在,它将创建它
如果表确实存在,它将确保它具有所需的模式

-- create table

create table if not exists `EntryType` (
  `EntryCode` varchar(2) primary key,
  `Name` varchar(256) not null
) engine = InnoDB default charset = utf8mb4;

-- modify table

alter table `EntryType`
  engine = InnoDB,
  character set utf8mb4;

alter table `EntryType`
  modify `EntryCode` varchar(2),
  drop primary key,
  add primary key (`EntryCode`);

alter table `EntryType`
  modify `Name` varchar(256) not null;

这种方法的问题

复制:重复列定义、引擎和字符集两次
费劲:手工编写这些查询并在每次添加或修改表时手动测试它们需要很多时间
命令式:从根本上说,这是一种对应该是声明性的东西的命令式方法

问题:是否有一些安全的方法来声明“应用”表模式?

幂等:可以在完全相同的结束状态下应用任意次数
无论该表是否已存在都有效
无论该表是否已包含数据都有效
无论是否存在对其他表的约束和外键引用,都可以工作

首选项:

纯sql解决方案是理想的
一个可靠且易于使用的cli解决方案可以工作
也可以接受相对简单的手工编码sql或node.js解决方案

6tr1vspr

6tr1vspr1#

正如bill karwin所建议的,skeema.io cli在一些简单的测试中运行得非常好。
这些文档在引导您完成安装过程方面做得不好,所以我在这里捕获了我发现的内容。

第一次架构获取

从github repo releases页面下载zip文件并解压缩。
把钥匙放好 skeema 在你的项目中的某个地方。在我的项目根中,我把它放在 bin 文件夹,因此从项目根目录 ./bin/skeema .
然后,确保你的mysql数据库正在运行并且你有连接信息。我的在本地运行 127.0.0.1 ,端口 3306 (mysql默认值,所以我不必输入它)。
在项目根目录中,我输入以下命令,通过获取数据库模式的当前状态来初始化。

./bin/skeema init -h 127.0.0.1 -u root -p --schema=MyDB -d schemas

一些细节:
我用了 --schema=MyDB 只跟踪一个数据库的选项。如果忽略此项,它将跟踪找到的所有数据库。
这个 -d schemas 选项表示将配置和模式文件存储在 schemas 目录。
使用 -p 选项,它将在运行命令后提示您输入密码。
然后它连接并检查您的数据库,创建 schemas 目录,并在其中编写一些表示当前架构状态的文件。你会注意到 .skeema 配置文件和 .sql 数据库中每个表的文件。

配置调整

然后我走进了房间 schemas/.skeema 配置文件并重命名 [production] 节至 [development] 因为这实际上是一个dev示例。通过这样做,我必须明确 development 因为 skeema 假设 production 作为默认值。
[可选,仅限于node.js项目] skeema 命令将从包含 .skeema 配置文件,但我不想担心这个问题,所以我在node.js中创建了一个脚本 package.json 基本上每次都是这样的文件。

{
  "scripts": {
    "skeema": "cd schemas && ../bin/skeema"
  },
}

现在,我可以从项目根目录(或项目中的任何其他位置)键入以下内容:

npm run skeema

第一个模式更改

当你在 schemas/.skeema 在配置文件中,我做了一些更改以更正设置这些表时的字符编码错误:
改变 default-character-set=utf8default-character-set=utf8mb4 改变 default-collation=utf8_general_cidefault--collation=utf8mb4_unicode_ci 我还向其中一个 .sql 文件夹:

CREATE TABLE `EntryType` (
  `EntryCode` varchar(2) NOT NULL,
  `Name` varchar(256) NOT NULL,
  `Foo` varchar(3), -- new column
  PRIMARY KEY (`EntryCode`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

推动架构更改

第一步是查看是否存在模式差异:

npm run skeema diff development

输出应与您所做的架构更改保持一致,例如:

2020-07-02 19:32:14 [INFO]  Generating diff of 127.0.0.1:3306 MyDB vs
                            /Users/chriscalo/Projects/my-project/schemas/*.sql
-- instance: 127.0.0.1:3306
USE `MyDB`;
ALTER TABLE `EntryType` ADD COLUMN `Foo` varchar(3) DEFAULT NULL;
2020-07-02 19:32:15 [INFO]  127.0.0.1:3306 MyDB: diff complete

然后推动模式更改:

yarn run skeema push development

就这样!

相关问题