Наличие «несоответствия внешнего ключа» в DELETE с несколькими SELECTS - PullRequest
0 голосов
/ 07 мая 2019

Я использую (в SQL) DELETE с несколькими SELECT с, но я получаю несоответствие внешнего ключа.

Оператор SQL:

DELETE FROM tile_items 
WHERE tile_id IN (SELECT id 
                  FROM tiles 
                  WHERE house_id IN (SELECT id 
                                     FROM houses 
                                     WHERE owner <> 0 
                                       AND owner NOT IN (SELECT id FROM players)))

Но я получаю ошибку

Несоответствие внешнего ключа - "tile_items" ссылается на "плитки"

Странно то, что то же утверждение, но с SELECT * FROM вместоиз DELETE FROM, возвращает все 44 совпадающих записи.

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

DELETE FROM tile_items 
WHERE tile_items.tile_id IN (SELECT id 
                             FROM tiles 
                             WHERE tiles.house_id IN (SELECT id FROM houses 
                                                      WHERE houses.owner <> 0 
                                                        AND houses.owner NOT IN (SELECT id FROM players)))

Не уверен, еслинеобходимо, но вот таблицы:

CREATE TABLE "tile_items" 
(
    "tile_id" INTEGER NOT NULL,
    "world_id" INTEGER NOT NULL DEFAULT 0,
    "sid" INTEGER NOT NULL,
    "pid" INTEGER NOT NULL DEFAULT 0,
    "itemtype" INTEGER NOT NULL,
    "count" INTEGER NOT NULL DEFAULT 0,
    "attributes" BLOB NOT NULL,
    UNIQUE ("tile_id", "world_id", "sid"),
    FOREIGN KEY ("tile_id") REFERENCES "tiles" ("id")
)

CREATE TABLE "tiles" 
(
    "id" INTEGER NOT NULL,
    "world_id" INTEGER NOT NULL DEFAULT 0,
    "house_id" INTEGER NOT NULL,
    "x" INTEGER NOT NULL,
    "y" INTEGER NOT NULL,
    "z" INTEGER NOT NULL,
    UNIQUE ("id", "world_id"),
    FOREIGN KEY ("house_id", "world_id") REFERENCES "houses" ("id", "world_id")
)

Поскольку ошибка привела только к таблицам "tile_items" и "плитки", размещены только эти схемы.

Надеюсь, кто-то может объяснить, почему яне могу УДАЛИТЬ, но могу ВЫБРАТЬ с этим утверждением, спасибо.

1 Ответ

1 голос
/ 07 мая 2019

Странно то, что тот же оператор, но с SELECT * FROM вместо DELETE FROM возвращает все 44 совпадающих записи.

Это не странно.Ошибка сообщает о проблеме с внешним ключом.Внешние ключи существуют для обеспечения согласованности данных при вставках, обновлениях и удалениях.Если вы просто выбираете данные, внешние ключи вообще не имеют значения.

Несоответствие внешнего ключа - "tile_items" ссылается на "плитки"

Эта ошибка на самом деле не включенаВаше заявление об удалении, но в базе данных и ее внешних ключах.Ваше утверждение верно, но ваша СУБД допускает недопустимые ограничения внешнего ключа и сообщает о них только при вставке, обновлении или удалении данных.На мой взгляд, было бы намного лучше, если бы СУБД заранее предотвращала подобные ситуации.

В вашей базе данных вы используете составные ключи.Уникальный ключ для таблицы tiles - (id, world_id), так что идентификатор плитки имеет значение только в сочетании с идентификатором мира.Один и тот же идентификатор плитки может означать одну плитку в мире X и другую в мире Y. (Было бы лучше, если бы вы не назвали этот столбец id, поскольку он не идентифицирует запись в таблице. Я бы предложилимя без идентификатора, например tile_no или tile_code для столбца, являющегося только частью уникально идентифицируемой группы столбцов. То же самое относится и к house_id, конечно.)

FOREIGN KEY ("tile_id") ССЫЛКИ "плитки" ("id")

Здесь вы хотите сказать, к какой строке tiles относится строка tile_items.Но что это?Одного идентификатора плитки недостаточно для идентификации строки в этой таблице, вам не хватает идентификатора мира.Должно быть:

FOREIGN KEY (tile_id, world_id) REFERENCES tiles (id, world_id)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...