SQLite的外键,ON DELETE CASCADE和SQLITE_CONSTRAINT
概述: 我有一个父/子表关系,那里的孩子可能包含2:n条记录与FK的回父。 当试图从父项中删除时,我得到一个SQLITE_CONSTRAINT错误。这是意外的,因为我已启用FK,让孩子注册ON DELETE CASCADE
,并有足够新的SQLite版本。SQLite的外键,ON DELETE CASCADE和SQLITE_CONSTRAINT
然而:我的孩子表原本没有ON DELETE CASCADE
。数据添加到父/子后,我添加了(并启用了FK)。从那里,我改名为原来的孩子&用约束创建了一个新表,最后移到了新表中。
表布局如下:
CREATE TABLE IF NOT EXISTS message (
message_id INTEGER PRIMARY KEY,
area_tag VARCHAR NOT NULL,
message_uuid VARCHAR(36) NOT NULL,
reply_to_message_id INTEGER,
to_user_name VARCHAR NOT NULL,
from_user_name VARCHAR NOT NULL,
subject, /* FTS @ message_fts */
message, /* FTS @ message_fts */
modified_timestamp DATETIME NOT NULL,
view_count INTEGER NOT NULL DEFAULT 0,
UNIQUE(message_uuid)
);
CREATE INDEX IF NOT EXISTS message_by_area_tag_index
ON message (area_tag);
CREATE VIRTUAL TABLE IF NOT EXISTS message_fts USING fts4 (
content="message",
subject,
message
);
CREATE TRIGGER IF NOT EXISTS message_before_update BEFORE UPDATE ON message BEGIN
DELETE FROM message_fts WHERE docid=old.rowid;
END;
CREATE TRIGGER IF NOT EXISTS message_before_delete BEFORE DELETE ON message BEGIN
DELETE FROM message_fts WHERE docid=old.rowid;
END;
CREATE TRIGGER IF NOT EXISTS message_after_update AFTER UPDATE ON message BEGIN
INSERT INTO message_fts(docid, subject, message) VALUES(new.rowid, new.subject, new.message);
END;
CREATE TRIGGER IF NOT EXISTS message_after_insert AFTER INSERT ON message BEGIN
INSERT INTO message_fts(docid, subject, message) VALUES(new.rowid, new.subject, new.message);
END;
CREATE TABLE IF NOT EXISTS message_meta (
message_id INTEGER NOT NULL,
meta_category INTEGER NOT NULL,
meta_name VARCHAR NOT NULL,
meta_value VARCHAR NOT NULL,
UNIQUE(message_id, meta_category, meta_name, meta_value),
FOREIGN KEY(message_id) REFERENCES message(message_id) ON DELETE CASCADE
);
在启动时,连接到数据库的I确保FK的启用后直接:
PRAGMA foreign_keys = ON;
其他详情:
- SQLite的版本: 3.7.17
- 访问:node-sqlite3
- 确切错误:
Error: SQLITE_CONSTRAINT: FOREIGN KEY constraint failed
这是造成我后来添加的约束的事实?
(请参阅更新1) 如何修复此问题而不丢失数据?
更新1:
我可以确认,仅选择消息(我相信,作为加入到该message_meta均消息之前ON DELETE CASCADE
消息)导致约束错误。其他人删除得很好,并正确地取出相关的message_meta记录。
回答我的问题 - 尝试不同的东西,我能找到的问题(一个或多个)几个小时后:
当我最初加入
ON DELETE CASCADE
条款,我这样做是通过重命名原始message_meta
表到message_meta_backup
,用该子句创建一个新表,然后将数据移入它:SELECT * FROM message_meta_backup INSERT INTO message_meta;
。我没有做的是丢弃备份表。由于#1或相关内容,我的数据库内部的东西变得混乱或混乱。
我想什么(没有工作):
REINDEX;
- 简单地丢弃备份表:
DROP TABLE message_meta_backup;
- ...等种种事情,我忘了:)
Wha牛逼没有工作:
终于结束了什么工作一度下探备份表,并使用sqlite3
外壳的.drop
命令完全重建数据库的组合:
> sqlite3 db/message.sqlite3
SQLite version 3.7.17 2013-05-20 00:56:22
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> drop table message_meta_backup;
sqlite> .quit
> sqlite3 db/message.sqlite3 ".dump" >> message_dump.sql
rm db/message.sqlite3
> cat message_dump.sql | sqlite3 db/message.sqlite3
我现在能DELETE FROM message ...
和有它正确地级联删除到message_meta
没有讨厌的错误:
sqlite> DELETE FROM message WHERE message_id IN(SELECT message_id FROM message WHERE area_tag='some_area' ORDER BY message_id desc limit -1 offset 200);
sqlite>
(!没有错误给出)
显示实际的错误信息。 –
@CL:错误:SQLITE_CONSTRAINT:FOREIGN KEY约束失败(也更新了OP) – NuSkooler
适用于我。你确定你已经显示的是数据库的当前模式吗? –