我有以下表格:如何將外鍵添加到現有的SQLite表中?
CREATE TABLE child(
id INTEGER PRIMARY KEY,
parent_id INTEGER,
description TEXT);
如何添加上parent_id
外鍵約束?假設外鍵已啓用。
大多數示例都假設您正在創建表格 - 我想將約束添加到現有表格中。
我有以下表格:如何將外鍵添加到現有的SQLite表中?
CREATE TABLE child(
id INTEGER PRIMARY KEY,
parent_id INTEGER,
description TEXT);
如何添加上parent_id
外鍵約束?假設外鍵已啓用。
大多數示例都假設您正在創建表格 - 我想將約束添加到現有表格中。
你不能。
雖然SQL-92語法外鍵添加到您的表將如下所示:
ALTER TABLE child ADD CONSTRAINT fk_child_parent
FOREIGN KEY (parent_id)
REFERENCES parent(id);
SQLite不支持的ADD CONSTRAINT
變體ALTER TABLE
命令(sqlite.org: SQL Features That SQLite Does Not Implement)的。
因此,在sqlite的3.6.1添加一個外鍵的唯一辦法是在CREATE TABLE
如下:
CREATE TABLE child (
id INTEGER PRIMARY KEY,
parent_id INTEGER,
description TEXT,
FOREIGN KEY (parent_id) REFERENCES parent(id)
);
不幸的是,你必須將現有的數據保存到臨時表,刪除舊錶,用FK約束創建新表,然後將數據從臨時表中複製回來。 (sqlite.org - FAQ: Q11)
如果您更改表並添加使用約束的列,則可以添加約束。
首先,創建表而不PARENT_ID:
CREATE TABLE child(
id INTEGER PRIMARY KEY,
description TEXT);
然後,ALTER TABLE:
ALTER TABLE child ADD COLUMN parent_id INTEGER REFERENCES parent(id);
很好習慣這個序列,但是這並不回答實際問題:*我想將約束添加到現有問題。* – Wolf 2018-01-17 12:12:48
如果您使用的是Firefox插件sqlite的經理,你可以做到以下幾點:
而不是再次刪除和創建表,你可以像這樣修改它。
在列文本框中,右鍵單擊列出的最後一列名稱以調出上下文菜單並選擇編輯列。 請注意,如果TABLE定義中的最後一列是PRIMARY KEY,則需要首先添加一個新列,然後編輯新列的列類型以添加FOREIGN KEY定義。 內的列類型中,附加一個逗號和數據類型後
FOREIGN KEY (parent_id) REFERENCES parent(id)
定義。 單擊更改按鈕,然後單擊危險操作對話框上的是按鈕。
參考: Sqlite Manager
請檢查https://www.sqlite.org/lang_altertable.html#otheralter
唯一模式變更命令直接SQLite的支持是 「重命名錶」和「添加列」上面顯示的命令。但是, 應用程序可以使用簡單的操作序列對錶 的格式進行其他任意更改。步驟進行是任意 更改某些表X的架構設計如下:
- 如果外鍵約束被啓用,使用PRAGMA foreign_keys = OFF禁用它們。
- 開始交易。
- 請記住所有索引和與 表X關聯的觸發器的格式。此信息將在下面的步驟8中需要。 這樣做的一個方法是運行如下查詢:SELECT type,sql FROM sqlite_master WHERE tbl_name ='X'。
- 使用CREATE TABLE構建一個新表格「new_X」,該表格位於 希望修改的表格格式X.當然,確保名稱「new_X」 不會與任何現有表名稱相沖突。使用的語句從X
- 內容傳送到一個new_x像:INSERT INTO SELECT的new_x ... FROM X.
- 刪除舊錶X:DROP TABLE X.
- 變化的new_x到X上使用的名稱: ALTER TABLE的new_x重命名爲X.
- 使用CREATE INDEX和CREATE TRIGGER來重建有十桌相關或許使用 觸發器和索引從上述步驟3爲指導保存的舊格式索引和 觸發器,使 變化視情況而定。
- 如果有任何意見請參考表X在由 架構變化的影響的方式,然後使用DROP VIEW丟棄這些意見,並重新 他們與任何變化都需要使用CREATE VIEW以適應架構 變化。
- 如果最初啓用了外鍵約束,則運行PRAGMA foreign_key_check以驗證模式更改沒有中斷 任何外鍵約束。
- 提交事務在步驟2中啓動。
- 如果最初啓用了外鍵約束,現在重新啓用它們 。
上述過程是完全一般的,並且即使 模式更改導致存儲在表中的信息發生變化,也會工作。因此, 上面的完整過程適用於刪除列, 更改列的順序,添加或刪除UNIQUE約束 或PRIMARY KEY,添加CHECK或FOREIGN KEY或NOT NULL約束, 或更改列的數據類型,例如。
首先在子表Cid
爲int
然後alter table
添加一列與下面的代碼。這樣你就可以添加外鍵Cid
作爲父表的主鍵,把它作爲子表的外鍵...希望它會幫助你,因爲它是爲我好:
ALTER TABLE [child]
ADD CONSTRAINT [CId]
FOREIGN KEY ([CId])
REFERENCES [Parent]([CId])
ON DELETE CASCADE ON UPDATE NO ACTION;
GO
這在SQLite中無效。這也是MS SQL語法。 – StilesCrisis 2017-10-27 00:27:47
你能夠!
請嘗試以下命令,並且不需要臨時表。它適用於Android Studio中的我。
db.execSQL("alter table child add column newCol integer REFERENCES parent(parentId)");
看來你沒有仔細閱讀過這個問題。問題是隻添加一個外部約束,而不是添加一個約束列。 – Wolf 2018-01-17 12:03:52
是的,你可以,無需添加新的列。你必須要小心,這樣做正確,以避免損壞數據庫,所以你應該完全備份您的數據庫試圖在此之前:
pragma writable_schema=1;
// replace the entire table's SQL definition, where new_sql_definition contains the foreign key clause you want to add
UPDATE SQLITE_MASTER SET SQL = new_sql_definition where name = 'child' and type = 'table';
// alternatively, you might find it easier to use replace, if you can match the exact end of the sql definition
// for example, if the last column was my_last_column integer not null:
UPDATE SQLITE_MASTER SET SQL = replace(sql, 'my_last_column integer not null', 'my_last_column integer not null, foreign key (col1, col2) references other_table(col1, col2)') where name = 'child' and type = 'table';
pragma writable_schema=0;
無論哪種方式,你可能會想先看看有什麼SQL定義是你在進行任何更改之前:如果您使用的替換()方法
select sql from SQLITE_MASTER where name = 'child' and type = 'table';
,你會發現它有用,在執行之前,通過運行第一測試代替()命令:
select update(sql, ...) from SQLITE_MASTER where name = 'child' and type = 'table';
我認爲重命名舊錶更容易,創建新表並將數據複製回來。然後,您可以刪除舊錶。 – tuinstoel 2009-12-11 19:20:24
是的,那很容易。我只是引用了sqlite的常見問題:http://www.sqlite.org/faq.html#q11。實際上,'RENAME TO'是sqlite 3當前支持的少數幾個'ALTER TABLE'變體之一。 – 2009-12-11 19:37:51
不應該是: FOREIGN KEY(parent_id)REFERENCES父級(id) 確實,Jonathan沒有給出「父表」的名稱。 其實表格應該是人名,但是... – igorludi 2012-09-07 08:51:29