361
339

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

SQLAlchemyの基本的な使い方

Last updated at Posted at 2020-01-11

#SQLAlchemyとは
SQLAlchemyとは,Pythonの中でよく利用されているORMの1つ.
ORMとは,Object Relational Mapperのことで,簡単に説明すると,テーブルとクラスを1対1に対応させて,そのクラスのメソッド経由でデータを取得したり,変更したりできるようにする存在.
##ORMの利点とは
###1. 異なるDBの違いを吸収してくれる
DBの種類によらず,同じソースコードで操作できるので,複数のDBを併用する場合や,DBを変更する場合にも,コードの書き換えの必要がない.
###2. SQLを書かなくてもよい
MySQLや,SQLite,PostgreSQLなどのDBを操作するにはSQLを使うが,SQLAlchemyを使うと,SQLを直接記述することなしに,DBを"Pythonic"に操作できる.

#SQLAlchemyの使い方
簡単な流れとしては,どのDBにどうやって接続するか,設定を行う.(その設定内容を保持したものがエンジンと呼ばれる)
その後,マッピングを行い,セッションを作成する.
そして,そのセッションを使ってDB操作を行う.

##1. DBエンジンを作成する

from sqlalchemy import create_engine
engine = create_engine("{dialect}+{driver}://{username}:{password}@{host}:{port}/{database}?charset={charset_type})

のように書き,エンジンのインスタンスを作成する.各要素の説明は以下の表のとおり.

要素         説明
dialect DBの種類を指定する.sqlite, mysql, postgresql, oracle, mssqlとか.
driver DBに接続するためのドライバーの指定をする.指定しなければ,"default" DBAPIになる.
username DBに接続することができるユーザ名を指定する.
password DBに接続するためのパスワードを指定する.
host ホスト名を指定する.localhostとかIPアドレスとか.
port ポート番号を指定する.指定しなければ,defaultのポート番号になるっぽい?
database 接続するデータベース名を指定する.
charset_type 文字コードを指定する.utf8とか.

例えば,以下のような感じ.(driverとportとcharset_typeは指定していない.)

engine = create_engine("mysql://scott:tiger@localhost/foo")

##2. モデルクラスを作る(テーブル定義を書く)
まずは,モデルベースクラスを作る.

from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()

そして,このベースクラスを拡張すると,ORMで扱えるモデルクラスになる.
例えば,以下のようにクラスを書けばよい.
また,モデルクラスを定義するときに,メソッドを追加することも可能である.

from sqlalchemy.schema import Column
from sqlalchemy.types import Integer, String

class User(Base):
    __tablename__ = "user"  # テーブル名を指定
    user_id = Column(Integer, primary_key=True)
    first_name = Column(String(255))
    last_name = Column(String(255))
    age = Column(Integer)

    def full_name(self):  # フルネームを返すメソッド
        return "{self.first_name} {self.last_name}"

上で定義したのは以下の表のようなテーブルをマッピングさせたクラス.

Field      Type        Null   Key   Default Extra
user_id int(11) NO PRI NULL auto_increment
first_name varchar(255) YES NULL
last_name varchar(255) YES NULL
age int(11) YES NULL
このテーブルをDBに作成するには,
Base.metadata.create_all(engine)

これで,Baseを継承しているテーブル郡が一括して作成される.
詳しいテーブル定義の内容は,以下.
SQLAlchemyでのテーブル定義
###metadataとは
上のコードでmetadataという言葉が出てきたが,metadataとは,DBの様々な情報を保持しているオブジェクトのこと.
このmetadataを使うと,既存のDBからテーブル定義をもってきたりすることもできる.

##3. セッションを作成する
SQLAlchemyはセッションを介してクエリを実行する.
そもそも,セッションとは,コネクションを確立してから切断するまでの一連の単位のこと.(DBとPythonコードを結びつける紐のようなものというイメージ)

セッションを作るクラスをsessionmakerで作る.(使うエンジンが一定なら,このとき指定する)

from sqlalchemy.orm import sessionmaker
SessionClass = sessionmaker(engine)  # セッションを作るクラスを作成
session = SessionClass()

詳しい扱い方は以下.
SQLAlchemyでのsessionの扱い方
##4. CRUD処理を行う
CRUDというのは,以下の機能をまとめた呼び方のこと.
・Create(新規作成)
・Read(読み取り)
・Update(更新)
・Destroy(削除)

セッションを閉じたり,明にcommit()しないとDBが更新されないので注意.

###INSERT
新規オブジェクトをsessionにadd()すると,INSERT対象になる.

user_a = User(first_name="first_a", last_name="last_a", age=20)
session.add(user_a)
session.commit()
user_id first_name last_name age
1 a a 20

###SELECT
テーブルからデータを取り出すには,queryを使う.

users = session.query(User).all()  # userテーブルの全レコードをクラスが入った配列で返す
user = session.query(User).first()  # userテーブルの最初のレコードをクラスで返す

詳しくは,参考文献.

###UPDATE
セッションから取り出したオブジェクトを変更すると,UPDATE対象になる.

user_a = session.query(User).get(1)  # 上で追加したuser_id=1のレコード
user_a.age = 10
session.commit()
user_id first_name last_name age
1 a a 10

###DELETE
セッションから取り出したオブジェクトをdelete()すると,DELETE対象になる.

user_a = session.query(User).get(1)
session.delete(user_a)
session.commit()

もしくは,検索条件にマッチするものを消すこともできる.

session.query(User).filter(User.user_id=1).delete()
session.commit()

##5. 既存のテーブルを使う場合
3では,新規のテーブルをマッピングしたクラスを作成したが,既存のテーブルをマッピングしたクラスを作りたいときもあるはず.
手順としては,Baseクラスにmetadataを渡し,__tablename__を既存のテーブル名に合わせて,autoloadをTrueにすればよい.
Baseクラスにmetadataを渡す方法としては,Baseクラスを作るときにengineを渡す方法

Base = declarative_base(bind=engine)

や,Baseクラスを作るときにmetadataを渡す方法

from sqlalchemy.schema import MetaData
meta = MetaData(engine)
meta.reflect()  # metadataを取得, meta=MetaData(engine, reflect=True)と同じ
Base = declarative_base(metadata=meta)

や,Baseクラスを作ったあとに付与する方法

Base = declarative_base()
Base.metadata.bind = engine

がある.
例えば,テーブル名がexisiting_userというテーブルが存在していたとすれば.

Base = declarative_base(bind=engine)

class Exisiting_user(Base):  # クラス名は何でもok
    __tablename__ = "exisiting_user"
    __table_args__ = {"autoload": True}

とすればよい.
#参考文献
この記事は以下の情報を参考にして執筆しました.
公式ドキュメント
PlaySQLAlchemy: SQLAlchemy入門
SQLAlchemyでデータベース定義を楽したい
【PythonのORM】SQLAlchemyで基本的なSQLクエリまとめ
sqlalchemyのautomapによる既存のDBからのmodelの生成について

361
339
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
361
339

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?