Удаление строк в промежуточной таблице ManyToMany - PullRequest
2 голосов
/ 28 сентября 2010

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

Чтобы прояснить проблему, вот небольшой код:

from elixir import *

metadata.bind = "sqlite:///test.db"
metadata.bind.echo = True

options_defaults['shortnames'] = True

class A(Entity):
    name = Field(Unicode(128))
    blist = ManyToMany("B",cascade='all,delete, delete-orphan')

class B(Entity):
    name = Field(Unicode(128))
    alist = ManyToMany("A",cascade='all,delete, delete-orphan') 

setup_all()
create_all()


a1 = A()
a1.name = u"john"

b1 = B()
b1.name = u"blue"

a1.blist.append(b1)

session.commit()

session.query(A).delete()
session.query(B).delete()

session.commit()

Дамп базы данных sqlite теперь содержит:

sqlite> .dump
PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE a (
    id INTEGER NOT NULL, 
    name VARCHAR(128), 
    PRIMARY KEY (id)
);
CREATE TABLE b (
    id INTEGER NOT NULL, 
    name VARCHAR(128), 
    PRIMARY KEY (id)
);
CREATE TABLE b_alist__a_blist (
    a_id INTEGER NOT NULL, 
    b_id INTEGER NOT NULL, 
    PRIMARY KEY (a_id, b_id), 
    CONSTRAINT a_blist_fk FOREIGN KEY(a_id) REFERENCES a (id), 
    CONSTRAINT b_alist_fk FOREIGN KEY(b_id) REFERENCES b (id)
);
INSERT INTO "b_alist__a_blist" VALUES(1,1);
COMMIT;

Я бы хотел, чтобы таблица "b_alist__a_blist" была очищена при удалении a1 или b1.

Возможно ли это без использования операторов ON DELETE, которые не всегда поддерживаются SQLite?

Поскольку я, конечно, не единственный, кто использует отношения ManyToMany с Elixir, решение этой проблемы, вероятно, тривиально.

Приведенный выше код генерирует предупреждения sqlalchemy:

SQLAlchemy / ОРМ / properties.py: 842: SAWarning: На B.alist, удалить-сирота каскад не поддерживается на многие ко многим или многие к одному отношения, когда single_parent не задавать. Установите single_parent = True на отношения ().
self._determine_direction ()

Это просто потому, что я сейчас случайно пытаюсь добавить каскадные опции в это отношение ManyToMany. Это должно быть признаком того, что delete-orphan не является правильным вариантом.

1 Ответ

1 голос
/ 28 сентября 2010

Я думаю, что нашел ответ. Во-первых, проблема та же самая с sqlalchemy .

Тогда, похоже, это происходит только при использовании этого синтаксиса:

session.query(B).delete()

Но можно получить желаемое поведение, используя:

session.delete(b)  #where b is an instance of B

Простая итерация session.delete(b) для каждого b может помочь.

Может быть, кто-то может прокомментировать эту разницу session.query().delete() и session.delete() ...

...