Как включить каскадное удаление внешнего ключа по умолчанию в SQLite?

SQLite v3.7.5

Есть ли способ включить внешние ключи SQLite с cascade delete включенным по умолчанию? Учитывая следующий пример:

CREATE TABLE [Parent] (
[ParentId] INTEGER  NOT NULL PRIMARY KEY AUTOINCREMENT,
[Name] VARCHAR(50)  UNIQUE NOT NULL
);

CREATE TABLE [Child] (
[ChildId] INTEGER  PRIMARY KEY AUTOINCREMENT NOT NULL,
[ParentId] INTEGER  NOT NULL,
[Name] VARCHAR(50)  NOT NULL,
FOREIGN KEY(ChildId) REFERENCES Child(ParentId) ON DELETE CASCADE
);

Единственный способ включить каскадное удаление — выполнить команду PRAGMA foreign_keys = true перед транзакцией:

using( var conn = new SQLiteConnection( _conn ) )
{
    conn.Open();
    var pragma = new SQLiteCommand( "PRAGMA foreign_keys = true;", conn );
    pragma.ExecuteNonQuery();

    var cmd = new SQLiteCommand( "Delete from Parent where ParentId = 1", conn );
    cmd.ExecuteNonQuery();
}

Есть ли параметр на уровне базы данных, который можно настроить вместо вызова команды pragma перед каждой транзакцией?

Я видел триггеры для включения каскадного удаления, но я ищу что-то, что просто включало бы PRAGMA foreign_keys = true на уровне базы данных.


person Metro Smurf    schedule 12.02.2011    source источник


Ответы (3)


В System.Data.SQLite 1.0.66 его нет, но в версии репозитория они обновлены до sqlite 3.7.4 и сделали новый атрибут строки подключения «Внешние ключи». Кто знает, когда это будет выпущено официально? Таким образом, вы можете установить это в строке подключения. Сейчас проект живет здесь: http://system.data.sqlite.org/index.html/doc/trunk/www/index.wiki

person P a u l    schedule 13.02.2011
comment
Спасибо, Пол. Надеемся, что официальный релиз объединится с форком и добавит атрибут строки подключения внешних ключей. Отличная информация! - person Metro Smurf; 13.02.2011

Нет, даже с параметрами времени компиляции.

Пока единственный способ — использовать pragma foreign_keys=on во время выполнения. Особая опасность заключается в том, что каждое приложение, работающее с базой данных, должно это делать.

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

person Mike Sherrill 'Cat Recall'    schedule 13.02.2011

Нет, в настоящее время нет способа (для обратной совместимости). См. ссылку, которую вы указали в разделе (2):

Ограничения внешнего ключа отключены по умолчанию (для обратной совместимости), поэтому их необходимо включать отдельно для каждого подключения к базе данных.

Однако это может быть изменено в будущем:

(Обратите внимание, однако, что будущие выпуски SQLite могут измениться, так что ограничения внешнего ключа будут включены по умолчанию. Осторожные разработчики не будут делать никаких предположений о том, включены ли внешние ключи по умолчанию, а вместо этого будут включать или отключать их по мере необходимости.)

person Femaref    schedule 12.02.2011
comment
Я надеялся, что есть параметр конфигурации или что-то подобное, которое я мог бы установить глобально. Похоже, что ответ Пола больше похож на настройку конфигурации в строке подключения. - person Metro Smurf; 13.02.2011