2

ManyToMany 関係を持つ 2 つのテーブルがあります。時々、データベースを更新する必要があるので、両方のテーブルから要素を削除します。ただし、削除された行間の関係は、自動的に作成された中間テーブル内に保存されます。

問題を明確にするために、ここに小さなコードを示します。

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;

a1またはb1が削除されたときに「b_alist__a_blist」テーブルを空にしたいと思います。

これは、SQLite で常にサポートされているとは限らない ON DELETE ステートメントを使用せずに可能ですか?

Elixir で ManyToMany 関係を使用しているのは確かに私だけではないので、この問題の解決策はおそらく簡単です。

上記のコードは、sqlalchemy の警告を生成します。

sqlalchemy/orm/properties.py:842: SAWarning: B.alist では、single_parent が設定されていない場合、delete-orphan カスケードは多対多または多対 1 の関係でサポートされません。relationship() で single_parent=True を設定します。
self._determine_direction()

これは、この ManyToMany 関係にカスケード オプションをランダムに追加しようとしているからです。これは、delete-orphan が正しいオプションではないことを示しているはずです。

4

1 に答える 1

1

私は答えを見つけたと思います。まず、問題は sqlalchemy だけでも同じです。

次に、これは次の構文を使用した場合にのみ発生するようです。

session.query(B).delete()

ただし、次を使用して目的の動作を取得できます。

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

session.delete(b)次に、 for each bの単純な反復でうまくいくかもしれません。

session.query().delete()たぶん、誰かがとのこの違いについてコメントできsession.delete()ます...

于 2010-09-28T11:57:27.557 に答える