Не удается добавить ограничение внешнего ключа при создании таблиц MySQL - PullRequest
0 голосов
/ 07 мая 2018

Метод 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 WARN]: в com.mysql.jdbc.MysqlIO.checkErrorPacket (MysqlIO.java:3593) [23:51:36 ПРЕДУПРЕЖДЕНИЕ]: в com.mysql.jdbc.MysqlIO.checkErrorPacket (MysqlIO.java:3525) [23:51:36 ПРЕДУПРЕЖДЕНИЕ]: at com.mysql.jdbc.MysqlIO.sendCommand (MysqlIO.java:1986) [23:51:36 WARN]: в com.mysql.jdbc.MysqlIO.sqlQueryDirect (MysqlIO.java:2140) [23:51:36 ПРЕДУПРЕЖДЕНИЕ]: в com.mysql.jdbc.ConnectionImpl.execSQL (ConnectionImpl.java:2620) [23:51:36 WARN]: в com.mysql.jdbc.ConnectionImpl.execSQL (ConnectionImpl.java:2570) [23:51:36 WARN]: в 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 WARN]: в power.managers.DatabaseManager.createTables (DatabaseManager.java:81) [23:51:36 WARN]: в power.managers.DatabaseManager.startDatabase (DatabaseManager.java:40) [23:51:36 WARN]: в power.managers.DatabaseManager. (DatabaseManager.java:30) [23:51:36 WARN]: в power.logic.ClanBattles.onEnable (ClanBattles.java:44) [23:51:36 WARN]: в org.bukkit.plugin.java.JavaPlugin.setEnabled (JavaPlugin.java:321) [23:51:36 WARN]: в org.bukkit.plugin.java.JavaPluginLoader.enablePlugin (JavaPluginLoader.java:340) [23:51:36 WARN]: в org.bukkit.plugin.SimplePluginManager.enablePlugin (SimplePluginManager.java:405) [23:51:36 WARN]: в org.bukkit.craftbukkit.v1_8_R3.CraftServer.loadPlugin (CraftServer.java:357) [23:51:36 WARN]: в org.bukkit.craftbukkit.v1_8_R3.CraftServer.enablePlugins (CraftServer.java:317) [23:51:36 WARN]: в org.bukkit.craftbukkit.v1_8_R3.CraftServer.reload (CraftServer.java:741) [23:51:36 ПРЕДУПРЕЖДЕНИЕ]: в org.bukkit.Bukkit.reload (Bukkit.java:535) [23:51:36 WARN]: в org.bukkit.command.defaults.ReloadCommand.execute (ReloadCommand.java:25) [23:51:36 WARN]: в org.bukkit.command.SimpleCommandMap.dispatch (SimpleCommandMap.java:141) [23:51:36 WARN]: в org.bukkit.craftbukkit.v1_8_R3.CraftServer.dispatchCommand (CraftServer.java:641) [23:51:36 WARN]: в net.minecraft.server.v1_8_R3.PlayerConnection.handleCommand (PlayerConnection.java:1162) [23:51:36 WARN]: в net.minecraft.server.v1_8_R3.PlayerConnection.a (PlayerConnection.java:997) [23:51:36 WARN]: в net.minecraft.server.v1_8_R3.PacketPlayInChat.a (PacketPlayInChat.java:45) [23:51:36 WARN]: в net.minecraft.server.v1_8_R3.PacketPlayInChat.a (PacketPlayInChat.java:1) [23:51:36 WARN]: в net.minecraft.server.v1_8_R3.PlayerConnectionUtils $ 1.run (SourceFile: 13) [23:51:36 WARN]: в java.util.concurrent.Executors $ RunnableAdapter.call (неизвестный источник) [23:51:36 WARN]: at 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 WARN]: в net.minecraft.server.v1_8_R3.DedicatedServer.B (DedicatedServer.java:374) [23:51:36 WARN]: в net.minecraft.server.v1_8_R3.MinecraftServer.A (MinecraftServer.java:654) [23:51:36 WARN]: вnet.minecraft.server.v1_8_R3.MinecraftServer.run (MinecraftServer.java:557) [23:51:36 WARN]: at java.lang.Thread.run (неизвестный источник)

Ответы [ 4 ]

0 голосов
/ 07 мая 2018

Вам просто нужно установить уникальное имя всех ограничений. Имя ограничений должно быть уникальным во всей базе данных.

0 голосов
/ 07 мая 2018

, почему у вас есть ИНОСТРАННЫЕ КЛЮЧИ (id) карты ССЫЛКИ (regionId) внутри вашей таблицы регионов? это должно быть иначе, не так ли (таблица регионов - это главная таблица и ее идентификатор, на который ссылаются карты таблиц)?

так должно быть и внутри таблицы создания таблиц DDL

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

То же самое с FK внутри таблицы местоположений, я думаю, что должно быть наоборот

0 голосов
/ 07 мая 2018

Вы не можете создать более одного первичного ключа в одной таблице Как вы сделали в таблице карт

"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)
); 
0 голосов
/ 07 мая 2018

Я думаю, что вы создаете внешние ключи в обратном направлении, что не правильно.

Поскольку ваша таблица map имеет regionId, вы должны создать для нее FOREIGN KEY в таблице карты, а не в самой region. Поэтому измените его в скрипте для создания таблицы map следующим образом:

FOREIGN KEY (regionId) REFERENCES regions(id)

То же самое относится к столбцу maxLocationId таблицы region. Внешний ключ должен быть определен в таблице region, а не в самом locations.

Любой внешний ключ должен ссылаться на PRIMARY KEY в ссылочной таблице, и если он не будет создан, mysql не создаст его.

Также вы должны соблюдать порядок зависимостей при создании таблиц и определении их ПЕРВИЧНЫХ КЛЮЧЕЙ, а затем создавать любые ссылающиеся FOREIGN KEY между ними.

Например, сначала вы должны создать таблицу region и определить ее ПЕРВИЧНЫЙ КЛЮЧ. После этого вы должны создать таблицу map, которая имеет ссылку на region, и теперь вы можете определить внешний ключ в таблице map, которая ссылается на таблицу id (или, как правило, ПЕРВИЧНЫЙ КЛЮЧ) таблицы region в его regionId столбец.

См. этот справочник по концепции и синтаксису создания внешних ключей.

...