Как добавить внешний ключ к существующей таблице SQLite?
у меня есть следующие таблицы:
CREATE TABLE child(
id INTEGER PRIMARY KEY,
parent_id INTEGER,
description TEXT);
Как добавить ограничение внешнего ключа на parent_id? Предположим, что внешние ключи включены.
большинство примеров предполагают, что вы создаете таблицу - я хотел бы добавить ограничение к существующему.
7 ответов:
ты не можешь.
хотя синтаксис SQL-92 для добавления внешнего ключа в таблицу будет выглядеть следующим образом:
ALTER TABLE child ADD CONSTRAINT fk_child_parent FOREIGN KEY (parent_id) REFERENCES parent(id);SQLite не поддерживает the
ADD CONSTRAINTвариантALTER TABLEкоманда (sqlite.org: функции SQL, которые SQLite не реализует).поэтому единственный способ добавить внешний ключ в 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 child ADD COLUMN parent_id INTEGER REFERENCES parent(id);
пожалуйста, проверьте https://www.sqlite.org/lang_altertable.html#otheralter
единственными командами изменения схемы, непосредственно поддерживаемыми SQLite, являются команды" переименовать таблицу "и" добавить столбец " показаны выше. Однако, приложения могут вносить другие произвольные изменения в формат таблицы используя простую последовательность операций. Шаги, чтобы сделать произвольные изменения в конструкции схемы некоторых таблиц X заключаются в следующем:
- если ограничения внешнего ключа включены, отключите их с помощью PRAGMA foreign_keys=выкл.
- запустить транзакцию.
- запомнить формат всех индексов и триггеров, связанных с таблица X. Эта информация будет необходима на этапе 8 ниже. Один из способов сделайте это, чтобы выполнить запрос следующим образом: выберите тип, sql из sqlite_master где tbl_name= 'X'.
- используйте CREATE TABLE для построения новой таблицы "new_X", которая находится в желаемый пересмотренный формат таблицы X. убедитесь, что имя " new_X" не сталкивается с любым существующим именем таблицы, конечно.
- перенос содержимого из X в new_X с помощью оператора типа: INSERT В new_X выберите ... От X.
- удалить старую таблицу х: падение в таблице X.
- измените имя new_X на X с помощью: ALTER TABLE new_X переименовать в X.
- используйте CREATE INDEX и CREATE TRIGGER для восстановления индексов и триггеры, связанные с таблицей X. Возможно, использовать старый формат этот триггеры и индексы, сохраненные в шаге 3 выше, делая изменения в соответствии с изменениями.
- если какие-либо представления ссылаются на таблицу X таким образом, что изменение схемы, а затем удалить эти представления с помощью DROP VIEW и воссоздать они с любыми изменениями необходимы для размещения схемы изменение с помощью создать представление.
- если ограничения внешнего ключа были первоначально включены, то запустите PRAGMA foreign_key_check, чтобы проверить, что схема перемены не сломались любые ограничения внешнего ключа.
- зафиксировать транзакцию, начатую на Шаге 2.
- если ограничения внешних ключей были первоначально включены, повторно включите их сейчас.
процедура выше полностью общая и будет работать, даже если изменение схемы приводит к изменению информации, хранящейся в таблице. Так вся вышеописанная процедура подходит для удаления столбца, изменение порядка столбцов, добавление или удаление ограничение уникальности или первичный ключ, добавление проверки или внешнего ключа или не нулевых ограничений, или изменение типа данных для столбца, например.
Если вы используете Firefox add-on sqlite-manager, вы можете сделать следующее:
вместо удаления и создания таблицы можно просто изменить это.
в текстовом поле столбцы щелкните правой кнопкой мыши на последнем имени столбца в списке, чтобы вызвать контекстное меню и выберите Редактировать столбец. Обратите внимание, что если последний столбец в определении таблицы является первичным ключом, то необходимо сначала добавить новый столбец, а затем изменить тип столбца новый столбец для добавления определения внешнего ключа. В поле Тип столбца добавьте запятую и
FOREIGN KEY (parent_id) REFERENCES parent(id)определение типа данных. Нажмите на кнопку Изменить, а затем нажмите кнопку Да в диалоговом окне опасной операции.
ссылка: SQLite Manager
да, можно, не добавляя новый столбец. Вы должны быть осторожны, чтобы сделать это правильно, чтобы избежать повреждения базы данных, поэтому вы должны полностью создать резервную копию базы данных, прежде чем пытаться это сделать.
для вашего конкретного примера:
CREATE TABLE child( id INTEGER PRIMARY KEY, parent_id INTEGER, description TEXT ); --- create the table we want to reference create table parent(id integer not null primary key); --- now we add the foreign key pragma writable_schema=1; update SQLITE_MASTER set sql = replace(sql, 'description TEXT)', 'description TEXT, foreign key (parent_id) references parent(id))' ) where name = 'child' and type = 'table'; --- test the foreign key pragma foreign_keys=on; insert into parent values(1); insert into child values(1, 1, 'hi'); --- works insert into child values(2, 2, 'bye'); --- fails, foreign key violationили более обобщенно:
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';если вы используете метод replace (), вы можете найти перед выполнением полезно сначала протестировать команду replace (), выполнив:
select update(sql, ...) from SQLITE_MASTER where name = 'child' and type = 'table';
Вы можете!
попробуйте выполнить следующую команду, и вам не понадобится временная таблица. Он работает для меня в Android Studio.
db.execSQL("alter table child add column newCol integer REFERENCES parent(parentId)");
Сначала добавьте столбец в дочернюю таблицу
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
Comments