我有一个现有的 MySQL 数据库,我正在尝试使用以下步骤迁移到 PostgreSQL。数据库相当简单——它有一些外键和其他约束,但没有触发器、过程等。
- 用于从现有 MySQL 数据库
DBIx::Class::Schema::Loader
生成一组类。Result
- 使用这些
Result
类为 PostgreSQL 生成一组CREATE TABLE
语句。 - 运行用于设置表的
CREATE TABLE
语句psql
(我还没有导入数据)。
我使用的脚本如下(删除了凭据和数据库名称):
#!/usr/bin/perl
use Modern::Perl;
use DBIx::Class::Schema::Loader qw/ make_schema_at /;
my $dsn = 'dbi:mysql:dbname=database';
my $user = '';
my $pass = '';
make_schema_at(
'MyDB::Schema',
{ debug => 1, dump_directory => './lib' },
[ $dsn, $user, $pass
],
);
my $schema = MyDB::Schema->connect($dsn, $user, $pass);
$schema->create_ddl_dir(['PostgreSQL'], '0.1', './', undef, { add_drop_table => 0 });
脚本成功运行,Result
类和.sql
文件(包含所有CREATE TABLE
语句)看起来都符合我的预期。
但是,有几个表有一个slug
列被标记为UNIQUE
原始 MySQL 模式,并导致以下行作为CREATE TABLE
语句的一部分:
"slug" character varying(50) NOT NULL,
CONSTRAINT "slug" UNIQUE ("slug")
当我尝试导入数据(使用psql < tables.sql
)时,我在每个表上都收到以下错误,在第一个表slug
之后有一个唯一列:
NOTICE: CREATE TABLE / UNIQUE will create implicit index "slug" for table "mytable"
ERROR: relation "slug" already exists
我的理解是索引名称在给定数据库中必须是唯一的。MySQL 没有这个问题,因为我只是在slug VARCHAR(50) NOT NULL UNIQUE
没有指定索引名称的情况下声明。
有没有办法让DBIx::Class
(或函数使用SQL::Translator
的create_ddl_dir
)在它输出的数据中生成一个唯一的索引名称?我并不特别关心索引的名称——尽管基于表名的东西是明智的。我查看了文档,但看不到任何允许这样做的参数。
我可以在导入文件之前手动编辑每个约束.sql
,但是有超过 250 个表和很多冲突——而且每次我调整迁移过程并且必须重新生成类和 SQL 时,我都必须这样做。