Как добавить внешний ключ в существующую таблицу SQLite?

У меня есть следующая таблица:

CREATE TABLE child( 
  id INTEGER PRIMARY KEY, 
  parent_id INTEGER, 
  description TEXT);

Как добавить ограничение внешнего ключа в parent_id? Предположим, что внешние ключи включены.

В большинстве примеров предполагается, что вы создаете таблицу - я хотел бы добавить ограничение к существующей.

112 голосов | спросил Dane O'Connor 11 FriEurope/Moscow2009-12-11T02:22:50+03:00Europe/Moscow12bEurope/MoscowFri, 11 Dec 2009 02:22:50 +0300 2009, 02:22:50

7 ответов


0

Вы не можете.

Хотя синтаксис 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, которых нет в 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 - часто задаваемые вопросы: Q11 )

ответил Daniel Vassallo 11 FriEurope/Moscow2009-12-11T02:26:55+03:00Europe/Moscow12bEurope/MoscowFri, 11 Dec 2009 02:26:55 +0300 2009, 02:26:55
0

Вы можете добавить ограничение, если измените таблицу и добавите столбец, который использует ограничение.

Сначала создайте таблицу без parent_id:

CREATE TABLE child( 
  id INTEGER PRIMARY KEY,  
  description TEXT);

Затем измените таблицу:

ALTER TABLE child ADD COLUMN parent_id INTEGER REFERENCES parent(id);
ответил Jorge Novaes 10 Mayam14 2014, 01:12:19
0

Пожалуйста, проверьте https://www.sqlite.org/lang_altertable.html#otheralter

  

Единственными командами изменения схемы, которые напрямую поддерживаются SQLite, являются   Команды «переименовать таблицу» и «добавить столбец» показаны выше. Тем не мение,   приложения могут вносить другие произвольные изменения в формат таблицы   используя простую последовательность операций. Шаги, чтобы сделать произвольным   Изменения в дизайне схемы некоторых таблиц X заключаются в следующем:

     
  1. Если ограничения внешнего ключа включены, отключите их с помощью PRAGMA   foreign_keys = OFF.
  2.   
  3. Начать транзакцию.
  4.   
  5. Запомните формат всех индексов и триггеров, связанных с   Таблица X. Эта информация понадобится на шаге 8 ниже. Один из способов   сделать это, чтобы выполнить запрос, подобный следующему: SELECT type, sql FROM   sqlite_master WHERE tbl_name = 'X'.
  6.   
  7. Используйте CREATE TABLE, чтобы создать новую таблицу "new_X", которая находится в   Нужен пересмотренный формат таблицы X. Убедитесь, что имя «new_X»   конечно, не конфликтует ни с одним из существующих имен таблиц.
  8.   
  9. Перенос содержимого из X в new_X с помощью следующего предложения: INSERT   INTO new_X SELECT ... FROM X.
  10.   
  11. Удалите старую таблицу X: DROP TABLE X.
  12.   
  13. Измените имя new_X на X, используя: ALTER TABLE new_X RENAME TO X.
  14.   
  15. Используйте CREATE INDEX и CREATE TRIGGER для восстановления индексов и   триггеры, связанные с таблицей X. Возможно, использовать старый формат   триггеры и индексы, сохраненные с шага 3 выше в качестве руководства, что делает   изменения в зависимости от изменений.
  16.   
  17. Если какие-либо представления ссылаются на таблицу X таким образом, на который влияют   измените схему, затем отбросьте эти представления, используя DROP VIEW, и создайте заново   их с любыми изменениями, необходимыми для размещения схемы   изменить с помощью CREATE VIEW.
  18.   
  19. Если ограничения внешнего ключа были изначально включены, запустите PRAGMA    foreign_key_check, чтобы проверить, что изменение схемы не сломалось    любые ограничения внешнего ключа.
  20.   
  21. Подтвердите транзакцию, начатую на шаге 2.
  22.   
  23. Если ограничения внешних ключей были изначально включены, включите их снова    Теперь.
  24.   

Вышеуказанная процедура носит общий характер и будет работать, даже если   изменение схемы приводит к изменению информации, хранящейся в таблице. Так   полная процедура, описанная выше, подходит для сбрасывания столбца,   изменение порядка столбцов, добавление или удаление УНИКАЛЬНОГО ограничения   или PRIMARY KEY, добавив ограничения CHECK или FOREIGN KEY или NOT NULL,   или, например, измените тип данных для столбца.

ответил situee 5 MaramThu, 05 Mar 2015 05:38:19 +03002015-03-05T05:38:19+03:0005 2015, 05:38:19
0

Если вы используете надстройку Firefox для sqlite-manager, вы можете сделать следующее:

Вместо того, чтобы снова создавать и создавать таблицу, можно просто изменить ее следующим образом.

В текстовом поле «Столбцы» щелкните правой кнопкой мыши имя последнего столбца в списке, чтобы открыть контекстное меню, и выберите «Изменить столбец». Обратите внимание, что если последний столбец в определении TABLE - PRIMARY KEY, то сначала необходимо добавить новый столбец, а затем отредактировать тип столбца нового столбца, чтобы добавить определение FOREIGN KEY. В поле «Тип столбца» добавьте запятую и

FOREIGN KEY (parent_id) REFERENCES parent(id)

определение после типа данных. Нажмите кнопку «Изменить», а затем кнопку «Да» в диалоговом окне «Опасная операция».

Ссылка: Sqlite Manager

ответил Baso 9 FebruaryEurope/MoscowbMon, 09 Feb 2015 00:27:27 +0300000000amMon, 09 Feb 2015 00:27:27 +030015 2015, 00:27:27
0

Да, вы можете, не добавляя новый столбец. Вы должны быть осторожны, чтобы сделать это правильно, чтобы не повредить базу данных, поэтому вам следует полностью создать резервную копию базы данных, прежде чем пытаться это сделать.

для вашего конкретного примера:

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';
ответил mwag 29 FriEurope/Moscow2017-12-29T06:07:05+03:00Europe/Moscow12bEurope/MoscowFri, 29 Dec 2017 06:07:05 +0300 2017, 06:07:05
0

ВЫ МОЖЕТЕ!

Попробуйте следующую команду, и вам не понадобится временная таблица. Это работает для меня в Android Studio.

db.execSQL("alter table child add column newCol integer REFERENCES parent(parentId)");
ответил saeed khalafinejad 20 72016vEurope/Moscow11bEurope/MoscowSun, 20 Nov 2016 10:05:12 +0300 2016, 10:05:12
0

Сначала добавьте столбец в дочернюю таблицу 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
ответил Tariq Nawaz Khan 25 J000000Monday16 2016, 20:47:28

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132