LoginSignup
28
15

More than 5 years have passed since last update.

SQLAlchemy で Delete するには?

Posted at

今回は SQLAlchemyDelete のやり方を書きます。

動作環境

  • Mac OS X 10.11.5
  • Python 3.5.1
  • MySQL Ver 14.14 Distrib 5.7.11, for osx10.11 (x86_64) using EditLine wrapper
  • SQLAlchemy 1.1.0
  • PyMySQL 0.7.4

サンプルコード

まずはシンプルに、テーブルから「name」カラムが "桑田 結子" となっているデータを検索して、削除します。

sqlalchemy_delete.py
# -*- coding:utf-8 -*-
import sqlalchemy
import sqlalchemy.orm
import sqlalchemy.ext.declarative

Base = sqlalchemy.ext.declarative.declarative_base()

class Student(Base):
    __tablename__ = 'students'
    id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
    name = sqlalchemy.Column(sqlalchemy.String(20))
    kana = sqlalchemy.Column(sqlalchemy.String(40))

def main():
    url = 'mysql+pymysql://root:@localhost/test_db?charset=utf8'

    engine = sqlalchemy.create_engine(url, echo=False)

    # テーブルを作成
    Base.metadata.create_all(engine)

    # セッションを作成
    Session = sqlalchemy.orm.sessionmaker(bind=engine)
    session = Session()

    # 全データ削除
    session.query(Student).delete()

    # データベースに追加するデータリスト
    student_list = [
        Student(id=1, name='石坂 優', kana='いしざか ゆう'),
        Student(id=2, name='杉野 誠一', kana='すぎの せいいち'),
        Student(id=3, name='桑田 結子', kana='くわた ゆうこ'),
        Student(id=4, name='栗原 愛', kana='くりはら あい'),
        Student(id=5, name='佐久間 仁', kana='さくま じん'),
    ]

    # データリストを一括追加
    session.add_all(student_list)

    # 削除対象のデータを検索
    found_student = session.query(Student).filter_by(name='桑田 結子').first()

    # 指定したデータを削除
    session.delete(found_student)

    # テーブルの全データを出力
    print_all_students(session)

    # データベースに反映
    session.commit()

# テーブルの全データを出力する関数
def print_all_students(session):
    students = session.query(Student).all()
    for student in students:
        print('%d, %s %s' % (student.id, student.name, student.kana))

if __name__ == '__main__':
    main()

次に応用として、フィルタ指定や IN 句指定でデータを削除します。

sqlalchemy_delete.py
# -*- coding:utf-8 -*-
import sqlalchemy
import sqlalchemy.orm
import sqlalchemy.ext.declarative

Base = sqlalchemy.ext.declarative.declarative_base()

class Student(Base):
    __tablename__ = 'students'
    id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
    name = sqlalchemy.Column(sqlalchemy.String(20))
    kana = sqlalchemy.Column(sqlalchemy.String(40))

def main():
    url = 'mysql+pymysql://root:@localhost/test_db?charset=utf8'

    engine = sqlalchemy.create_engine(url, echo=False)

    # テーブルを作成
    Base.metadata.create_all(engine)

    # セッションを作成
    Session = sqlalchemy.orm.sessionmaker(bind=engine)
    session = Session()

    # 全データ削除
    print("====== session.query(Student).delete() =====")
    session.query(Student).delete()
    print_all_students(session)

    # データベースに追加するデータリスト
    student_list = [
        Student(id=1, name='石坂 優', kana='いしざか ゆう'),
        Student(id=2, name='杉野 誠一', kana='すぎの せいいち'),
        Student(id=3, name='桑田 結子', kana='くわた ゆうこ'),
        Student(id=4, name='栗原 愛', kana='くりはら あい'),
        Student(id=5, name='佐久間 仁', kana='さくま じん'),
    ]

    # データリストを一括追加
    print("====== session.add_all(student_list) ======")
    session.add_all(student_list)
    print_all_students(session)

    # フィルタで指定して削除
    print("====== session.query(Student).filter(Student.id==2).delete() =====")
    session.query(Student).filter(Student.id==2).delete()
    print_all_students(session)

    # IN 句で指定して削除
    print("====== session.query(Student).filter(Student.id.in_([3, 4])).delete(synchronize_session='fetch') =====")
    session.query(Student).filter(Student.id.in_([3, 4])).delete(synchronize_session='fetch')
    print_all_students(session)

    # データベースに反映
    session.commit()

# テーブルの全データを出力する関数
def print_all_students(session):
    students = session.query(Student).all()
    for student in students:
        print('%d, %s %s' % (student.id, student.name, student.kana))

if __name__ == '__main__':
    main()

まとめ

Session クラスに add_all というメソッドがあるので、全データ削除は delete_all かな?と思われる方もいそうですが、そうではないので注意ですね。

また、delete メソッドの引数 synchronize_session のデフォルト引数は 'evaluate' となっているため、IN 句で指定して削除する場合は 'fetch' を指定しないと例外が発生します。
詳しくは公式ドキュメントを参照してください。

[エラーメッセージ]
sqlalchemy.exc.InvalidRequestError: Could not evaluate current criteria in Python. Specify 'fetch' or False for the synchronize_session parameter.

公式ドキュメント>Query API>delete(synchronize_session='evaluate')
http://docs.sqlalchemy.org/en/rel_1_1/orm/query.html#sqlalchemy.orm.query.Query.delete

28
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
28
15