#8.3 リレーショナルデータベース
詳細は前の記事を。
「RDBMSとSQLについて」
https://qiita.com/Taka20200105/items/c58ac4e610954c6d263b
##8.3.1 SQL
- SQLは二つにのカテゴリに分類される。
- DDL(データ定義言語):テーブルデータベースの作成、削除、制約、許可。
- DML(データ操作言語):データの挿入、選択、更新、削除などの処理
##8.3.2 DB-API
- APIとはサービスにアクセスするために呼び出す関数を集めたもの。APIを開設するとは、一つの窓を作って外のソフトウェアと連携させることと理解。鎖国中の出島みたいなもの。
- DB-APIはRDBMSにアクセスするためのPythonの標準のAPI。
- DB-APIの主要関数まとめ
関数 | 意味 |
---|---|
connect() | DBへの接続を開設する。引数指定可能。 |
cursor() | クエリーを管理するカーソルオブジェクトを作成 |
execute()とexecutemany() | DBに対して一つまたは複数の複数のSQLコマンドを送る。 |
fechone()、fetchmany()、fetch all() | DBに対して一つまたは複数の複数のSQLコマンドを送る。 |
##8.3.3 SQLite
- SQLiteは通常のファイルにDBを格納する。
- 非常に移植性が高いRDBMS。
>>> import sqlite3
#enterprise.dbという名前のDBを作る。
>>> conn=sqlite3.connect("enterprise.db")
>>> curs=conn.cursor()
#zooというテーブルの作成。
#critterという可変長文字列のプライマリーキー列
#countという数字の列
#damagesという浮動小数点列
>>> curs.execute("""CREATE TABLE zoo (critter VARCHAR(20)PRIMARY KEY,count INT,damages FLOAT)""")
<sqlite3.Cursor object at 0x10b215f80>
#execute以下の文字列がDMLコマンド
#INSERT INTO zoo VALUES(〜)で行の追加。
>>> curs.execute("""INSERT INTO zoo VALUES("duck",5,0.0)""")
<sqlite3.Cursor object at 0x10b23d030>
>>> curs.execute("""INSERT INTO zoo VALUES("bear",2,1000.0)""")
<sqlite3.Cursor object at 0x10b23d030>
#以下のような追加方法でも追加可能。
#3個の疑問符は挿入予定を示す。
>>> ins="""INSERT INTO zoo (critter,count,damages) VALUES(?,?,?)"""
>>> curs.execute(ins, ("weasel",1,2000.0))
<sqlite3.Cursor object at 0x10b23d030>
#"SELECT * FROM テーブル名"で全ての行と列の選択
>>> curs.execute("SELECT * FROM zoo")
<sqlite3.Cursor object at 0x10b23d030>
#結果の取得
>>> rows=curs.fetchall()
>>> print(rows)
[('duck', 5, 0.0), ('bear', 2, 1000.0), ('weasel', 1, 2000.0)]
#count順にソートする。
>>> curs.execute("SELECT * FROM zoo ORDER BY count")
<sqlite3.Cursor object at 0x10b23d030>
>>> curs.fetchall()
[('weasel', 1, 2000.0), ('bear', 2, 1000.0), ('duck', 5, 0.0)]
#count順でかつ降順で。
>>> curs.execute("SELECT * FROM zoo ORDER BY count DESC")
<sqlite3.Cursor object at 0x10b23d030>
>>> curs.fetchall()
[('duck', 5, 0.0), ('bear', 2, 1000.0), ('weasel', 1, 2000.0)]
#最もdamagesが最大のものの選択。
>>> curs.execute("""SELECT * FROM zoo WHERE damages=(SELECT MAX(damages) FROM zoo)""")<sqlite3.Cursor object at 0x10b23d030>
>>> curs.fetchall()
[('weasel', 1, 2000.0)]
#接続とカーソルを開いたら使い終わったら閉じなければならない。
>>> curs.close
<built-in method close of sqlite3.Cursor object at 0x10b23d030>
>>> conn.close
<built-in method close of sqlite3.Connection object at 0x10b1d4ab0>
##8.3.4 MySQL
- MySQLはSQLiteとは異なり、本物は本物のサーバー。
##8.3.5 PostgreSQL
- PostgreSQLはMySQLよりも高度な本格的なオープンソースのRDBMSである。
##8.3.6 SQLAIchemyライブラリ
- SQLは全てのRDBMSで同じというわけじゃない。
- DB-APIは共通APIレベルまでしか対応していい。→個々のDBの違いを埋めようとするライブラリの中で、クロスデータベースPythonライブラリであるSQLAIchemyは多くの支持がある。
- 特徴
- DB接続のプール、SQLコマンドの実行、結果のリターン処理。
- SQLの文をPythonの式として表現するSQL表現言語である。
- ORMレイヤ。このレイヤはSQL表現言語を使ってアプリケーションコードとRDBMS構造を結びつける。
- dialect + driver ://user:password@host:port /dbnameという接続文字列形式だ。
- dialect:DBのタイプ
- driver:そのDBに対して使いたいと思っているドライバ。
- userとpassword:DB認証文字列
- hostとport:DBサーバーの位置
- dbname:最初に接続するサーバー上のDB。
###8.3.6.1 エンジンレイヤ
- 必要なドライバはSQLAIchemyが接続文字列から判断してくれる。
- 接続文字列を変更するだけで他のタイプのDBに移植可能。
>>> import sqlalchemy as sa
#DBを開設し、記憶領域を作る。
#ResultProxyというオブジェクトが返される。
#dbnameを省略するとDBのファイルをメモリ内に格納する。
#SQliteの文字列ではhost, port,user,password不要。
>>> conn=sa.create_engine("sqlite://")
#3つの列を持つzooテーブルを作る。
>>> conn.execute("""CREATE TABLE zoo (critter VARCHAR(20) PRIMARY KEY,count INT,damages FLOAT)""")
<sqlalchemy.engine.result.ResultProxy object at 0x108ee3210>
#f3個のデータを挿入する。
>>> ins="""INSERT INTO zoo (critter,count,damages) VALUES(?,?,?)"""
>>> conn.execute(ins,"duck",10,0.0)
<sqlalchemy.engine.result.ResultProxy object at 0x108ee3290>
>>> conn.execute(ins,"bear",2,1000.0)
<sqlalchemy.engine.result.ResultProxy object at 0x108ee3350>
>>> conn.execute(ins,"weasel",1,2000.0)
<sqlalchemy.engine.result.ResultProxy object at 0x108ee32d0>
#zooの全ての情報をDBに要求する。
>>> rows=conn.execute("SELECT*FROM zoo")
>>> print(rows)
<sqlalchemy.engine.result.ResultProxy object at 0x108ee3110>
>>> for row in rows:
... print(row)
...
('duck', 10, 0.0)
('bear', 2, 1000.0)
('weasel', 1, 2000.0)
#感想
最初勉強した時はMySQLやPostgteSQLはSQLの種類かと思っていたが、今回の復習ではそれが違うことに気づいた。
上記はRDBMSであり、言語ではない。
そして多くのDBにはそれぞれの方言が実装されており、その方言の違いを埋めようと出ててきたのがSQLAIchemyライブラリ。
DB毎にドライバをインストールせず、接続文字列で判断してくれるとは賢いですな。
######参考文献
「Bill Lubanovic著 『入門 Python3』(オライリージャパン発行)」