2016-07-15 212 views
0

概述: 我有一個父/子表關係,那裏的孩子可能包含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記錄。

+0

顯示實際的錯誤信息。 –

+0

@CL:錯誤:SQLITE_CONSTRAINT:FOREIGN KEY約束失敗(也更新了OP) – NuSkooler

+0

適用於我。你確定你已經顯示的是數據庫的當前模式嗎? –

回答

0

回答我的問題 - 嘗試不同的東西,我能找到的問題(一個或多個)幾個小時後:

  • 當我最初加入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> 

(!沒有錯誤給出)