我正在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)))
但是我得到一个错误
外键不匹配-引用“ tiles”的“ 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”和“ tiles”,因此仅发布了这些模式。
希望有人可以解释为什么我不能删除但可以用此语句进行选择,谢谢。
答案 0 :(得分:1)
奇怪的是,同一条语句使用SELECT * FROM而不是DELETE FROM返回了所有44条匹配记录。
这并不奇怪。该错误报告外键问题。存在外键以确保插入,更新和删除中的数据一致性。如果只选择数据,那么外键根本没有关系。
外键不匹配-引用“ tiles”的“ tile_items”
此错误不是真正在您的delete语句上,而是在数据库及其外键上。您的陈述是有效的,但是您的DBMS允许无效的外键约束,并且仅在您插入,更新或删除数据时才报告它们。我认为DBMS事先阻止这种情况会更好。
在数据库中,您正在使用复合键。 tiles
表的唯一键是(id, world_id)
,因此图块ID仅与世界ID结合使用才有意义。相同的图块ID可以表示世界X中的一个图块,而世界Y中的另一个图块。(最好不要将此列称为id
,因为它不能识别表中的记录。我会为仅属于唯一标识列组一部分的列建议一个非ID名称,例如tile_no
或tile_code
。house_id
当然也适用。)
外键(“ tile_id”)参考“ tiles”(“ id”)
您要在此处说出tiles
行所指向的tile_items
行。但是,这是什么?仅图块ID不足以标识该表中的行,因为您缺少世界ID。它必须是:
FOREIGN KEY (tile_id, world_id) REFERENCES tiles (id, world_id)