我有一个数据库(MariaDB),我需要从中删除外键。没有什么比这更容易了,因为
alter table people_contacts
drop foreign key people_contacts;
完美地完成工作。 当然,假设上面是表和键的名称
但我来这里询问是因为“外部”并发症。应用程序是一个 Java 应用程序,它使用:
因此,在测试过程中我运行了 H2 数据库,显然 H2 不支持
drop foreign key
。我一整天都在尝试使用 H2 兼容性属性,唯一的结果是有时会更改错误。
因此,我无法创建一个独特的迁移脚本,该脚本应该在嵌入测试数据库时首先在 H2 中运行,然后在实际数据库(包括生产)中的 MariaDB 上运行。我可能会创建不同版本的迁移,但我真的很想避免这种方法。 有人会看到任何解决方法吗? 提前致谢!
虽然认为解决问题的唯一方法是重建表,但我发现这样做还有另一个重要原因。
我的放置命令
alter table people_contacts drop foreign key people_contacts_fk;
不是
SQL 标准方式,它应该是
ALTER TABLE people_contacts DROP CONSTRAINT people_contacts_fk
正如@evgenijryazanov 在他的评论中指出的那样。
在 H2 中它会完美地工作,但在我的例子中,我抱怨该名称缺乏约束。
这实际上是我在创建表格时遇到的问题。
详情
调查 H2 中未找到的约束(请注意,H2 DB 的生命周期为几毫秒,随后被销毁),我打开了创建表的 DDL,发现它被创建为
create table people_contacts (
... fields ...,
foreign key (person_id) references people (id)
);
通过这种方式,约束不会被赋予显式名称,并且它将具有的名称将取决于数据库。我在持久数据库中找到的名称没有明确给出,而且我没有意识到它,因为这是一个早期的错误,不符合项目的实践。 所以(
抱歉!)我没有检查原始 DDL,而是向 H2 收取不兼容性费用。
约束应创建为
create table people_contacts (
... fields ...,
constraint explicit_name_for_it foreign key (person_id) references people (id)
);
为了确保在 H2 和 MariaDB 中都使用给定名称创建,并且稍后可以根据需要使用给定名称删除它。
当然,约束的工作方式没有问题,并且类似的错误可能仍然未被发现,直到您需要删除这样的约束并且需要通过名称来调用它。
吸取的教训
始终让约束具有明确的名称,因为将来您可能需要“按名称调用它们”来删除或更改它们。不幸的是,我发现其中一些是错误地创建的。我想解决这个问题的方法是:
将后缀为“old”的表重命名使用具有显式名称的约束重建表