【问题标题】:Cannot add foreign key constraint creating tables MySQL无法添加外键约束创建表MySQL
【发布时间】:2018-05-07 04:38:06
【问题描述】:

createTable() 方法有效,我一直在创建其他简单的表,没有问题。

我正在使用 MySQL 服务器 8.0

这是对表格的测试,然后我将编写一个脚本来创建它们。我一直有这个错误:

无法创建表,SQLException: 无法添加外键约束

但我不知道出了什么问题。

    if(!database.checkTable("maps")){
        String maps = "CREATE TABLE maps (" 
                + "name VARCHAR(32) NOT NULL,"
                + "mapType VARCHAR(32) NOT NULL,"
                + "world VARCHAR(32) NOT NULL,"
                + "referenceId INT(32) NOT NULL,"
                + "regionId INT(32) NOT NULL,"
                + "testmode BIT(1) NOT NULL,"
                + "edition BIT(1) NOT NULL,"
                + "finished BIT(1) NOT NULL,"
                + "PRIMARY KEY (name, referenceId, regionId))"
                + "ENGINE = InnoDB "
                + "DEFAULT CHARACTER SET = utf8;";
        database.createTable(maps);
    }
    if(!database.checkTable("regions")){
        String regions = "CREATE TABLE regions ("
                + "id INT(32) NOT NULL AUTO_INCREMENT," 
                + "minLocationId INT(32) NOT NULL,"
                + "maxLocationId INT(32) NOT NULL,"
                + "PRIMARY KEY (id, minLocationId, maxLocationId),"
                + "CONSTRAINT `regionMapFk`"
                + "FOREIGN KEY (id)"
                + "REFERENCES maps (regionId)"
                + "ON DELETE CASCADE "
                + "ON UPDATE CASCADE)"
                + "ENGINE = InnoDB "
                + "DEFAULT CHARACTER SET = utf8;";
        database.createTable(regions);
    }
    if(!database.checkTable("locations")){
        String locations = "CREATE TABLE locations ("   
                + "id INT(16) NOT NULL AUTO_INCREMENT, "
                + "x INT(16) NOT NULL, "
                + "y INT(16) NOT NULL, "
                + "z INT(16) NOT NULL, "
                + "PRIMARY KEY(id),"
                + "CONSTRAINT `minLocationRegionFk`"
                + "FOREIGN KEY (id)"
                + "REFERENCES regions (minLocationId)"
                + "ON DELETE CASCADE "
                + "ON UPDATE CASCADE,"
                + "CONSTRAINT `maxLocationRegionFk`"
                + "FOREIGN KEY (id)"
                + "REFERENCES regions (maxLocationId)"
                + "ON DELETE CASCADE "
                + "ON UPDATE CASCADE,"
                + "CONSTRAINT `locationMapFk`"
                + "FOREIGN KEY (id)"
                + "REFERENCES maps (referenceId)"
                + "ON DELETE CASCADE "
                + "ON UPDATE CASCADE)"
                + "ENGINE = InnoDB "
                + "DEFAULT CHARACTER SET = utf8;";
        database.createTable(locations);
    }

[23:51:36 WARN]:java.sql.SQLException:无法添加外键 约束 [23:51:36 警告]:在 com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1073) [23:51:36 警告]:在 com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3593)[23:51:36 警告]:在 com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3525)[23:51:36 警告]:在 com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1986) [23:51:36 警告]:在 com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2140) [23:51:36 警告]:在 com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2620) [23:51:36 警告]:在 com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2570) [23:51:36 警告]:在 com.mysql.jdbc.StatementImpl.execute(StatementImpl.java:779)[23:51:36 警告]:在 com.mysql.jdbc.StatementImpl.execute(StatementImpl.java:622)[23:51:36 警告]:在 power.database.MySQL.createTable(MySQL.java:104) [23:51:36 警告]:在 power.managers.DatabaseManager.createTables(DatabaseManager.java:81) [23:51:36 警告]:在 power.managers.DatabaseManager.startDatabase(DatabaseManager.java:40) [23:51:36 警告]:在 power.managers.DatabaseManager.(DatabaseManager.java:30) [23:51:36 警告]:在 power.logic.ClanBattles.onEnable(ClanBattles.java:44)[23:51:36 警告]: 在 org.bukkit.plugin.java.JavaPlugin.setEnabled(JavaPlugin.java:321) [23:51:36 警告]:在 org.bukkit.plugin.java.JavaPluginLoader.enablePlugin(JavaPluginLoader.java:340) [23:51:36 警告]:在 org.bukkit.plugin.SimplePluginManager.enablePlugin(SimplePluginManager.java:405) [23:51:36 警告]:在 org.bukkit.craftbukkit.v1_8_R3.CraftServer.loadPlugin(CraftServer.java:357) [23:51:36 警告]:在 org.bukkit.craftbukkit.v1_8_R3.CraftServer.enablePlugins(CraftServer.java:317) [23:51:36 警告]:在 org.bukkit.craftbukkit.v1_8_R3.CraftServer.reload(CraftServer.java:741) [23:51:36 警告]:在 org.bukkit.Bukkit.reload(Bukkit.java:535) [23:51:36 警告]:在 org.bukkit.command.defaults.ReloadCommand.execute(ReloadCommand.java:25) [23:51:36 警告]:在 org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:141) [23:51:36 警告]:在 org.bukkit.craftbukkit.v1_8_R3.CraftServer.dispatchCommand(CraftServer.java:641) [23:51:36 警告]:在 net.minecraft.server.v1_8_R3.PlayerConnection.handleCommand(PlayerConnection.java:1162) [23:51:36 警告]:在 net.minecraft.server.v1_8_R3.PlayerConnection.a(PlayerConnection.java:997) [23:51:36 警告]:在 net.minecraft.server.v1_8_R3.PacketPlayInChat.a(PacketPlayInChat.java:45) [23:51:36 警告]:在 net.minecraft.server.v1_8_R3.PacketPlayInChat.a(PacketPlayInChat.java:1) [23:51:36 警告]:在 net.minecraft.server.v1_8_R3.PlayerConnectionUtils$1.run(SourceFile:13) [23:51:36 警告]:在 java.util.concurrent.Executors$RunnableAdapter.call(未知来源) [23:51:36 警告]:在 java.util.concurrent.FutureTask.run(未知 来源)[23:51:36 警告]:在 net.minecraft.server.v1_8_R3.SystemUtils.a(源文件:44)[23:51:36 警告]:在 net.minecraft.server.v1_8_R3.MinecraftServer.B(MinecraftServer.java:715) [23:51:36 警告]:在 net.minecraft.server.v1_8_R3.DedicatedServer.B(DedicatedServer.java:374) [23:51:36 警告]:在 net.minecraft.server.v1_8_R3.MinecraftServer.A(MinecraftServer.java:654) [23:51:36 警告]:在 net.minecraft.server.v1_8_R3.MinecraftServer.run(MinecraftServer.java:557) [23:51:36 警告]:在 java.lang.Thread.run(未知来源)

【问题讨论】:

  • 您能否提供适当的堆栈跟踪来检查来自 MySQL 的整个错误消息?
  • 这是一个来自我的世界控制台的错误,即所有堆栈跟踪,实际上相同的错误显示了两次,第一次创建区域表,第二次创建位置表。查询似乎没问题,但可能我缺少一些东西

标签: mysql sql minecraft


【解决方案1】:

我认为您正在反向创建外键,这是不正确的。

由于您的map 表有regionId,那么您应该在映射表中为它创建一个FOREIGN KEY,而不是在region 本身中。因此,在创建map 表的脚本中更改它:

FOREIGN KEY (regionId) REFERENCES regions(id)

这同样适用于region 表的maxLocationId 列。外键应在region 表中定义,而不是在locations 本身中。

任何外键都应该在引用表中引用PRIMARY KEY,如果没有,mysql 不会创建它。

此外,您应该在创建表和定义它们的 PRIMARY KEY 时保持依赖顺序,然后在它们之间创建任何引用 FOREIGN KEY。

例如,您应该首先创建region 表并定义其主键。之后,您应该创建引用 regionmap 表,现在您可以在 map 表中定义外键,该表引用 region 表的 id(或通常是主键)它的regionId 专栏。

有关创建外键的概念和语法,请参阅this 参考。

【讨论】:

  • 好吧,我制作了一个 ERR 图来测试表之间的关系,当我删除他地图表的一行时,我想删除与地图相关的区域和位置。顺便说一下,我会尝试按相反的顺序做,并检查它是否有效。
  • 我更改了关系的顺序,但是当我尝试删除地图时,该区域和与该地图相关的 3 个位置仍然存在,但如果我删除位置 id 1 并且地图存在referenceId = 1 时,该地图也将被删除。如果我删除 id = 2 的位置并且一个区域的 minLocationId = 2 或 maxLocationId = 2,也会发生同样的情况
  • 您创建外键的问题解决了吗?
  • 我仍然无法删除地图及其相关行。
  • 当你想从location表中删除一个map和它相关的location行,你应该维护一个one-to-manymap表到location表的关系。这意味着您应该在location 表中有一个名为(例如)map_id 的外键,这意味着location 表中的许多位置记录属于map 表中的一个记录(一个映射记录是许多位置记录的父级)。使用它并在ON DELETECASCADE 的外键上设置正确的属性,您将能够在地图记录上删除,然后位置记录将被删除。
【解决方案2】:

为什么您的区域表中有 FOREIGN KEY (id) REFERENCES 映射 (regionId)?它应该是另一种方式不是吗(区域表是主表,它的 id 由表映射引用)?

所以在create table maps DDL里面应该是这样的

FOREIGN KEY (regionId) REFERENCES region (id)
ON DELETE CASCADE 
ON UPDATE CASCADE

位置表中的 FK 也是如此,我认为应该反过来

【讨论】:

    【解决方案3】:

    您不能在一张表中创建多个主键 就像你在地图表中所做的那样

    "CREATE TABLE maps (" 
                    + "name VARCHAR(32) NOT NULL,"
                    + "mapType VARCHAR(32) NOT NULL,"
                    + "world VARCHAR(32) NOT NULL,"
                    + "referenceId INT(32) NOT NULL,"
                    + "regionId INT(32) NOT NULL,"
                    + "testmode BIT(1) NOT NULL,"
                    + "edition BIT(1) NOT NULL,"
                    + "finished BIT(1) NOT NULL,"
                    + "PRIMARY KEY (name, referenceId, regionId))"
                    + "ENGINE = InnoDB "
                    + "DEFAULT CHARACTER SET = utf8;";
    

    要创建外键约束,您必须提供该表的主键的引用,您要使用它来绑定当前表

    看看 https://www.w3schools.com/sql/sql_foreignkey.asp

    CREATE TABLE Orders (
        OrderID int NOT NULL,
        OrderNumber int NOT NULL,
        PersonID int,
        PRIMARY KEY (OrderID),
        FOREIGN KEY (PersonID) REFERENCES Persons(PersonID)
    ); 
    

    【讨论】:

      【解决方案4】:

      您只需为所有约束设置一个唯一名称。 约束名称在整个数据库中必须唯一。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-04-25
        • 2014-02-26
        • 2013-03-10
        • 2021-11-05
        相关资源
        最近更新 更多