Essential_SQLAlchemy 2 th学習ノートのCoreモジュール
23525 ワード
SQL Expression LanguageはオリジナルSQL言語を簡単にパッケージ化した2大モジュールSQLAlchemy Core and ORM: Core:SQL Expression Languageを実行するインタフェース を提供する ORM
インストール:SQLAlchemyおよび関連データベースドライバ
データベース接続文字列フォーマット:ここを参照してください
例えばSQLiteは次のようになります.
create_Engineの残りのパラメータ: echo:実行するsql文とそのパラメータをlog印刷するかどうか.デフォルトはFalse encoding:デフォルトutf-8 isolation_レベル:独立性レベル pool_recycle:接続回収間隔を指定します.これはMySQL接続の8時間メカニズムにとって特に重要です.デフォルト-1 接続の取得
Schema and Types
•Generic•SQL Standard•Vendor specific•User definedの4種類のコレクション
SQLAlchemyは、異なるデータベースと互換性を持つために多くのgeneric typesを定義しています.これらのタイプは
SQLAlchemy
Python
SQL
BigInteger
int
BIGINT
Boolean
bool
BOOLEAN or SMALLINT
Date
datetime.date
DATE (SQLite: STRING)
DateTime
datetime.datetime
DATETIME (SQLite: STRING)
Enum
str
ENUM or VARCHAR
Float
float or Decimal
FLOAT or REAL
Integer
int
INTEGER
Interval
datetime.timedelta
INTERVAL or DATE from epoch
LargeBinary
byte
BLOB or BYTEA
Numeric
decimal.Decimal
NUMERIC or DECIMAL
Unicode
unicode
UNICODE or VARCHAR
Text
str
CLOB or TEXT
Time
datetime.time
DATETIME
これらのタイプがjsonタイプをサポートするデータベースなど、あなたを満たすことができない場合は、
Metadataは、データベースへの迅速なアクセスを目的としています.多くのTableオブジェクトの集合と見なすことができ,engin,connectionに関する情報もいくつかある.
Tableオブジェクトは、1番目のパラメータが名前、2番目のパラメータがMetadataオブジェクト、その後のパラメータがColumnオブジェクトとして構築する.Columnオブジェクトのパラメータは、名前、タイプ、およびその他です.
注意:ここでdefault、onupdate属性は直接値ではなくcallableオブジェクトです.例えばdatetime.now()は、インスタンスごとにインスタンス化、更新される時間ではなく、永遠にこの値であるからです.比較的有用なのは
キーとコンストレイント(Keys and Constraints)キーとコンストレイントは、上述したようにkwargsによってColumnに定義してもよいし、後でオブジェクトによって追加してもよい.関連クラスは、最も一般的な3つの
インデックス(Index)
この定義はTableコンストラクタに配置する必要があります.
関連関係と外部キー制約(Relationships and ForeignKeyConstraints)
注意:ここでForeignKeyは、参照ではなく、データベース内のテーブル名.カラム名に対応する文字列パラメータを使用します.モジュール間の相互依存性を分離しても使用できます:
注:デフォルトではcreate_all
このセクションのコードは次のとおりです.
SQLAlchemy-Coreモジュール
データの挿入:
もちろんあなたもそうすることができます.
上記のプリコンパイル文は次のとおりです.
実際のプロシージャは、insオブジェクトの内部でcompile()メソッドを呼び出して上記の文にコンパイルし、パラメータをinsに格納する.compile().params辞書にあります.次に、前に取得したconnectionオブジェクトからstatementを実行します.
もちろん、このように調べることもできます.
一括挿入:
注意:すべての辞書パラメータが同じkeysを持っていることを確認してください.
検索
もちろん、文字列の代わりに文字列を使用することもできます.
connection.executeが返すrp変数は
私たちもこのように書くことができます.
ResultProxyにより、クエリ結果はindex,name,or Column objectを介してカラムデータにアクセスできます.例:
ResultProxyを反復することもできます.次のようにします.
ResultProxyの残りの結果セットを取得する方法 first() fetchone() fetchall() scalar():Returns a single value if a query results in a single record with one column. keys()カラム名 を取得
ResultProxyの上記の方法の選択についてのアドバイス:1、fetchone()ではなくfirst()を使用して単一のレコードを取得する.fetchone()呼び出し後も開いているconnectionsが続いているため、うっかりすると問題を起こしやすい.2、fetchall()ではなく反復方式ですべての結果を取得し、メモリをより節約します.3、scalar()を使用して単行単列の結果を取得する場合は、複数の行を返すと例外が放出されることに注意してください.
戻りカラム数の制御
ツールバーの
結果セットを返すバーの数を制限
内蔵SQL関数
ここにいるよsql.funcモジュール内
フィルタリング
whereで使用できる句要素 between(cleft, cright) concat(column_two) Concatenate column with column_two distinct() in_([list]) is_(None) Find where the column is None (commonly used for Null checks with None) contains(string) Find where the column has string in it (case-sensitive) endswith(string) Find where the column ends with string (case-sensitive) like(string) Find where the column is like string (case-sensitive) startswith(string) Find where the column begins with string (case-sensitive) ilike(string) Find where the column is like string (this is not case-sensitive)
もちろん、notin_のような一連のnotxxxメソッドも含まれています.()、唯一の例外はisnot()
オペレータ +,-,*,/,% ==,!=,,<=,>= AND,OR,NOT,pythonキーワードのせいでand_(),or_(),not_() の代わりに
+記号は、文字列の結合にも使用できます.
注意:castは別の関数で、数値を通貨形式に変換するタイプ変換とprint('{}-{:.2f}'.format(row.cokie_name,row.inv_cost))を行うことができる.この行為は一致している.
update
delete
joins
join()、outerjoin()関数、select_from()関数
最終的に生成されたSQL文は次のとおりです.
outerjoin
テーブル別名関数alias()
グループ化
chaining
オリジナルSQLの実行
返されるのはResultProxyオブジェクト1で、元のSQLを完全に使用します.
2、部分的に原始SQL、text()関数を採用する
異常
SQLALchemyは多くの異常を定義している.私たちは関心を持っています:AttributeErrors,IntegratyErrors.などの試験と説明を行うために、まず次の文を実行してください.
IntegratyError異常は、制約に違反した場合に発生します.例えば、一意性の制約に違反するなどです.
すべてのSQLAlchemy異常処理方式は上記の考え方であり,[SQLAlchemyError](http://docs.sqlalchemy.org/en/latest/core/exceptions.html)で取得できる情報は次のとおりです. orig :The DBAPI exception object. params:The parameter list being used when this exception occurred. statement :The string SQL statement being invoked when this exception occurred.
トランザクションTransactions
インストール:SQLAlchemyおよび関連データベースドライバ
pip install sqlalchemy pymysql
データベースへの接続データベース接続文字列フォーマット:ここを参照してください
mysql://username:password@hostname/database
postgresql://username:password@hostname/database
sqlite:////absolute/path/to/database
oracle://scott:[email protected]:1521/orcl
例えばSQLiteは次のようになります.
from sqlalchemy import create_engine
engine = create_engine('sqlite:///cookies.db')
engine2 = create_engine('sqlite:///:memory:')
engine3 = create_engine('sqlite:////home/cookiemonster/cookies.db')
engine4 = create_engine('sqlite:///c:\\Users\\cookiemonster\\cookies.db')
:create_engine engine , , engine connection
MySQL 8 : pool_recycle=3600
from sqlalchemy import create_engine
engine = create_engine('mysql+pymysql://cookiemonster:[email protected]/cookies', pool_recycle=3600)
create_Engineの残りのパラメータ:
from sqlalchemy import create_engine
engine = create_engine('mysql+pymysql://cookiemonster:chocolatechip' \
'@mysql01.monster.internal/cookies', pool_recycle=3600)
connection = engine.connect()
Schema and Types
•Generic•SQL Standard•Vendor specific•User definedの4種類のコレクション
SQLAlchemyは、異なるデータベースと互換性を持つために多くのgeneric typesを定義しています.これらのタイプは
sqlalchemy.types
モジュールに定義されており、sqlalchemyから直接インポートすることもできます.タイプ対応表は次のとおりです.SQLAlchemy
Python
SQL
BigInteger
int
BIGINT
Boolean
bool
BOOLEAN or SMALLINT
Date
datetime.date
DATE (SQLite: STRING)
DateTime
datetime.datetime
DATETIME (SQLite: STRING)
Enum
str
ENUM or VARCHAR
Float
float or Decimal
FLOAT or REAL
Integer
int
INTEGER
Interval
datetime.timedelta
INTERVAL or DATE from epoch
LargeBinary
byte
BLOB or BYTEA
Numeric
decimal.Decimal
NUMERIC or DECIMAL
Unicode
unicode
UNICODE or VARCHAR
Text
str
CLOB or TEXT
Time
datetime.time
DATETIME
これらのタイプがjsonタイプをサポートするデータベースなど、あなたを満たすことができない場合は、
sqlalchemy.dialects
モジュールの対応するデータベースのタイプを使用する必要があります.例えばfrom sqlalchemy.dialects.postgresql import JSON
Metadata & Table & Column Metadataは、データベースへの迅速なアクセスを目的としています.多くのTableオブジェクトの集合と見なすことができ,engin,connectionに関する情報もいくつかある.
MetaData.tables
でこれらの表オブジェクト辞書にアクセスして、表オブジェクトを定義する前にMetadataをインスタンス化する必要があります.from sqlalchemy import MetaData
metadata = MetaData()
Tableオブジェクトは、1番目のパラメータが名前、2番目のパラメータがMetadataオブジェクト、その後のパラメータがColumnオブジェクトとして構築する.Columnオブジェクトのパラメータは、名前、タイプ、およびその他です.
from sqlalchemy import Table, Column, Integer, Numeric, String, ForeignKey
cookies = Table('cookies', metadata,
Column('cookie_id', Integer(), primary_key=True),
Column('cookie_name', String(50), index=True),
Column('cookie_recipe_url', String(255)),
Column('cookie_sku', String(55)),
Column('quantity', Integer()),
Column('unit_cost', Numeric(12, 2))
)
from datetime import datetime
from sqlalchemy import DateTime
users = Table('users', metadata,
Column('user_id', Integer(), primary_key=True),
Column('username', String(15), nullable=False, unique=True),
Column('email_address', String(255), nullable=False),
Column('phone', String(20), nullable=False),
Column('password', String(25), nullable=False),
Column('created_on', DateTime(), default=datetime.now),
Column('updated_on', DateTime(), default=datetime.now, onupdate=datetime.now)
注意:ここでdefault、onupdate属性は直接値ではなくcallableオブジェクトです.例えばdatetime.now()は、インスタンスごとにインスタンス化、更新される時間ではなく、永遠にこの値であるからです.比較的有用なのは
onupdate
であり、更新のたびにメソッドまたは関数が呼び出されます.キーとコンストレイント(Keys and Constraints)キーとコンストレイントは、上述したようにkwargsによってColumnに定義してもよいし、後でオブジェクトによって追加してもよい.関連クラスは、最も一般的な3つの
from sqlalchemy import PrimaryKeyConstraint, UniqueConstraint, CheckConstraint
などのベースのsqlalchemyモジュールで定義されます.PrimaryKeyConstraint('user_id', name='user_pk'), 。
UniqueConstraint('username', name='uix_username')
CheckConstraint('unit_cost >= 0.00', name='unit_cost_positive')
インデックス(Index)
from sqlalchemy import Index
Index('ix_cookies_cookie_name', 'cookie_name')
この定義はTableコンストラクタに配置する必要があります.
Index('ix_test', mytable.c.cookie_sku, mytable.c.cookie_name))
のように、後に定義することもできます.関連関係と外部キー制約(Relationships and ForeignKeyConstraints)
from sqlalchemy import ForeignKey
orders = Table('orders', metadata,
Column('order_id', Integer(), primary_key=True),
Column('user_id', ForeignKey('users.user_id')),
Column('shipped', Boolean(), default=False)
)
line_items = Table('line_items', metadata,
Column('line_items_id', Integer(), primary_key=True),
Column('order_id', ForeignKey('orders.order_id')),
Column('cookie_id', ForeignKey('cookies.cookie_id')),
Column('quantity', Integer()),
Column('extended_cost', Numeric(12, 2))
)
注意:ここでForeignKeyは、参照ではなく、データベース内のテーブル名.カラム名に対応する文字列パラメータを使用します.モジュール間の相互依存性を分離しても使用できます:
ForeignKeyConstraint(['order_id'], ['orders.order_id'])
テーブル・モードの作成または永続化(Persisting the Table)サンプル・コードでは、すべてのTable定義と、追加のモード定義がmetadataオブジェクトに関連付けられていることがわかります.このmetadataオブジェクトを使用してテーブルを作成できます.metadata.create_all(engine)
注:デフォルトではcreate_all
は既存のテーブルを再作成するので、安全に複数回呼び出すことができ、Ablembicなどのデータベース移行ライブラリとの統合も非常に友好的で、追加の手動符号化を必要としません.このセクションのコードは次のとおりです.
from datetime import datetime
from sqlalchemy import (MetaData, Table, Column, Integer, Numeric, String,
DateTime, ForeignKey, create_engine)
metadata = MetaData()
cookies = Table('cookies', metadata,
Column('cookie_id', Integer(), primary_key=True),
Column('cookie_name', String(50), index=True),
Column('cookie_recipe_url', String(255)),
Column('cookie_sku', String(55)),
Column('quantity', Integer()),
Column('unit_cost', Numeric(12, 2))
)
users = Table('users', metadata,
Column('user_id', Integer(), primary_key=True),
Column('customer_number', Integer(), autoincrement=True),
Column('username', String(15), nullable=False, unique=True),
Column('email_address', String(255), nullable=False),
Column('phone', String(20), nullable=False),
Column('password', String(25), nullable=False),
Column('created_on', DateTime(), default=datetime.now),
Column('updated_on', DateTime(), default=datetime.now, onupdate=datetime.now)
)
orders = Table('orders', metadata,
Column('order_id', Integer(), primary_key=True),
Column('user_id', ForeignKey('users.user_id'))
)
line_items = Table('line_items', metadata,
Column('line_items_id', Integer(), primary_key=True),
Column('order_id', ForeignKey('orders.order_id')),
Column('cookie_id', ForeignKey('cookies.cookie_id')),
Column('quantity', Integer()),
Column('extended_cost', Numeric(12, 2))
)
engine = create_engine('sqlite:///:memory:')
metadata.create_all(engine)
SQLAlchemy-Coreモジュール
データの挿入:
ins = cookies.insert().values(
cookie_name="chocolate chip",
cookie_recipe_url="http://some.aweso.me/cookie/recipe.html",
cookie_sku="CC01",
quantity="12",
unit_cost="0.50"
)
print(str(ins))
もちろんあなたもそうすることができます.
from sqlalchemy import insert
ins = insert(cookies).values(
cookie_name="chocolate chip",
cookie_recipe_url="http://some.aweso.me/cookie/recipe.html",
cookie_sku="CC01",
quantity="12",
unit_cost="0.50"
)
上記のプリコンパイル文は次のとおりです.
INSERT INTO cookies
(cookie_name, cookie_recipe_url, cookie_sku, quantity, unit_cost)
VALUES
(:cookie_name, :cookie_recipe_url, :cookie_sku, :quantity, :unit_cost)
実際のプロシージャは、insオブジェクトの内部でcompile()メソッドを呼び出して上記の文にコンパイルし、パラメータをinsに格納する.compile().params辞書にあります.次に、前に取得したconnectionオブジェクトからstatementを実行します.
result = connection.execute(ins)
もちろん、このように調べることもできます.
ins = cookies.insert()
result = connection.execute(
ins,
cookie_name='dark chocolate chip',
cookie_recipe_url='http://some.aweso.me/cookie/recipe_dark.html',
cookie_sku='CC02',
quantity='1',
unit_cost='0.75'
)
result.inserted_primary_key
一括挿入:
inventory_list = [
{
'cookie_name': 'peanut butter',
'cookie_recipe_url': 'http://some.aweso.me/cookie/peanut.html',
'cookie_sku': 'PB01',
'quantity': '24',
'unit_cost': '0.25'
},
{
'cookie_name': 'oatmeal raisin',
'cookie_recipe_url': 'http://some.okay.me/cookie/raisin.html',
'cookie_sku': 'EWW01',
'quantity': '100',
'unit_cost': '1.00'
}
]
result = connection.execute(ins, inventory_list)
注意:すべての辞書パラメータが同じkeysを持っていることを確認してください.
検索
from sqlalchemy.sql import select
s = select([cookies])
rp = connection.execute(s)
results = rp.fetchall()
もちろん、文字列の代わりに文字列を使用することもできます.
s = select("""SELECT cookies.cookie_id, cookies.cookie_name,
cookies.cookie_recipe_url, cookies.cookie_sku, cookies.quantity,
cookies.unit_cost FROM cookies""")
connection.executeが返すrp変数は
ResultProxy
オブジェクト(DBAPIのcursorオブジェクトのカプセル化)です.私たちもこのように書くことができます.
from sqlalchemy.sql import select
s = cookies.select()
rp = connection.execute(s)
results = rp.fetchall()
ResultProxyにより、クエリ結果はindex,name,or Column objectを介してカラムデータにアクセスできます.例:
first_row = results[0]
first_row[1] # 1 ,by index
first_row.cookie_name # by name
first_row[cookies.c.cookie_name] #by Column object.
ResultProxyを反復することもできます.次のようにします.
rp = connection.execute(s)
for record in rp:
print(record.cookie_name)
ResultProxyの残りの結果セットを取得する方法
ResultProxyの上記の方法の選択についてのアドバイス:1、fetchone()ではなくfirst()を使用して単一のレコードを取得する.fetchone()呼び出し後も開いているconnectionsが続いているため、うっかりすると問題を起こしやすい.2、fetchall()ではなく反復方式ですべての結果を取得し、メモリをより節約します.3、scalar()を使用して単行単列の結果を取得する場合は、複数の行を返すと例外が放出されることに注意してください.
戻りカラム数の制御
s = select([cookies.c.cookie_name, cookies.c.quantity])
rp = connection.execute(s)
print(rp.keys())
result = rp.first()
ツールバーの
s = select([cookies.c.cookie_name, cookies.c.quantity])
s = s.order_by(cookies.c.quantity)
rp = connection.execute(s)
for cookie in rp:
print('{} - {}'.format(cookie.quantity, cookie.cookie_name))
# desc
from sqlalchemy import desc
s = select([cookies.c.cookie_name, cookies.c.quantity])
s = s.order_by(desc(cookies.c.quantity))
結果セットを返すバーの数を制限
s = select([cookies.c.cookie_name, cookies.c.quantity])
s = s.order_by(cookies.c.quantity)
s = s.limit(2)
rp = connection.execute(s)
print([result.cookie_name for result in rp])
内蔵SQL関数
ここにいるよsql.funcモジュール内
#sum
from sqlalchemy.sql import func
s = select([func.sum(cookies.c.quantity)])
rp = connection.execute(s)
print(rp.scalar())
#count
s = select([func.count(cookies.c.cookie_name)])
rp = connection.execute(s)
record = rp.first()
print(record.keys())
print(record.count_1) # ,_, ,
#
s = select([func.count(cookies.c.cookie_name).label('inventory_count')])
rp = connection.execute(s)
record = rp.first()
print(record.keys())
print(record.inventory_count)
フィルタリング
#where
s = select([cookies]).where(cookies.c.cookie_name == 'chocolate chip')
rp = connection.execute(s)
record = rp.first()
print(record.items()) # row items() 。
#like
s = select([cookies]).where(cookies.c.cookie_name.like('%chocolate%'))
rp = connection.execute(s)
for record in rp.fetchall():
print(record.cookie_name)
whereで使用できる句要素
もちろん、notin_のような一連のnotxxxメソッドも含まれています.()、唯一の例外はisnot()
オペレータ
+記号は、文字列の結合にも使用できます.
s = select([cookies.c.cookie_name, 'SKU-' + cookies.c.cookie_sku])
for row in connection.execute(s):
print(row)
from sqlalchemy import cast
s = select([cookies.c.cookie_name,
cast((cookies.c.quantity * cookies.c.unit_cost),
Numeric(12,2)).label('inv_cost')])
for row in connection.execute(s):
print('{} - {}'.format(row.cookie_name, row.inv_cost))
注意:castは別の関数で、数値を通貨形式に変換するタイプ変換とprint('{}-{:.2f}'.format(row.cokie_name,row.inv_cost))を行うことができる.この行為は一致している.
from sqlalchemy import and_, or_, not_
s = select([cookies]).where(
and_(
cookies.c.quantity > 23,
cookies.c.unit_cost < 0.40
)
)
for row in connection.execute(s):
print(row.cookie_name)
from sqlalchemy import and_, or_, not_
s = select([cookies]).where(
or_(
cookies.c.quantity.between(10, 50),
cookies.c.cookie_name.contains('chip')
)
)
for row in connection.execute(s):
print(row.cookie_name)
update
from sqlalchemy import update
u = update(cookies).where(cookies.c.cookie_name == "chocolate chip")
u = u.values(quantity=(cookies.c.quantity + 120))
result = connection.execute(u)
print(result.rowcount)
s = select([cookies]).where(cookies.c.cookie_name == "chocolate chip")
result = connection.execute(s).first()
for key in result.keys():
print('{:>20}: {}'.format(key, result[key]))
delete
from sqlalchemy import delete
u = delete(cookies).where(cookies.c.cookie_name == "dark chocolate chip")
result = connection.execute(u)
print(result.rowcount)
s = select([cookies]).where(cookies.c.cookie_name == "dark chocolate chip")
result = connection.execute(s).fetchall()
print(len(result))
joins
join()、outerjoin()関数、select_from()関数
columns = [orders.c.order_id, users.c.username, users.c.phone,
cookies.c.cookie_name, line_items.c.quantity,
line_items.c.extended_cost]
cookiemon_orders = select(columns)
cookiemon_orders = cookiemon_orders.select_from(orders.join(users).join(
line_items).join(cookies)).where(users.c.username ==
'cookiemon')
result = connection.execute(cookiemon_orders).fetchall()
for row in result:
print(row)
最終的に生成されたSQL文は次のとおりです.
SELECT orders.order_id, users.username, users.phone, cookies.cookie_name,
line_items.quantity, line_items.extended_cost FROM users JOIN orders ON
users.user_id = orders.user_id JOIN line_items ON orders.order_id =
line_items.order_id JOIN cookies ON cookies.cookie_id = line_items.cookie_id
WHERE users.username = :username_1
outerjoin
columns = [users.c.username, func.count(orders.c.order_id)]
all_orders = select(columns)
all_orders = all_orders.select_from(users.outerjoin(orders))
all_orders = all_orders.group_by(users.c.username)
result = connection.execute(all_orders).fetchall()
for row in result:
print(row)
テーブル別名関数alias()
>>> manager = employee_table.alias('mgr')
>>> stmt = select([employee_table.c.name],
... and_(employee_table.c.manager_id==manager.c.id,
... manager.c.name=='Fred'))
>>> print(stmt)
SELECT employee.name
FROM employee, employee AS mgr
WHERE employee.manager_id = mgr.id AND mgr.name = ?
グループ化
columns = [users.c.username, func.count(orders.c.order_id)]
all_orders = select(columns)
all_orders = all_orders.select_from(users.outerjoin(orders))
all_orders = all_orders.group_by(users.c.username)
result = connection.execute(all_orders).fetchall()
for row in result:
print(row)
chaining
def get_orders_by_customer(cust_name, shipped=None, details=False):
columns = [orders.c.order_id, users.c.username, users.c.phone]
joins = users.join(orders)
if details:
columns.extend([cookies.c.cookie_name, line_items.c.quantity,
line_items.c.extended_cost])
joins = joins.join(line_items).join(cookies)
cust_orders = select(columns)
cust_orders = cust_orders.select_from(joins)
cust_orders = cust_orders.where(users.c.username == cust_name)
if shipped is not None:
cust_orders = cust_orders.where(orders.c.shipped == shipped)
result = connection.execute(cust_orders).fetchall()
return result
オリジナルSQLの実行
返されるのはResultProxyオブジェクト1で、元のSQLを完全に使用します.
result = connection.execute("select * from orders").fetchall()
print(result)
2、部分的に原始SQL、text()関数を採用する
from sqlalchemy import text
stmt = select([users]).where(text("username='cookiemon'"))
print(connection.execute(stmt).fetchall())
異常
SQLALchemyは多くの異常を定義している.私たちは関心を持っています:AttributeErrors,IntegratyErrors.などの試験と説明を行うために、まず次の文を実行してください.
from datetime import datetime
from sqlalchemy import (MetaData, Table, Column, Integer, Numeric, String,
DateTime, ForeignKey, Boolean, create_engine,
CheckConstraint)
metadata = MetaData()
cookies = Table('cookies', metadata,
Column('cookie_id', Integer(), primary_key=True),
37
Column('cookie_name', String(50), index=True),
Column('cookie_recipe_url', String(255)),
Column('cookie_sku', String(55)),
Column('quantity', Integer()),
Column('unit_cost', Numeric(12, 2)),
CheckConstraint('quantity > 0', name='quantity_positive')
)
users = Table('users', metadata,
Column('user_id', Integer(), primary_key=True),
Column('username', String(15), nullable=False, unique=True),
Column('email_address', String(255), nullable=False),
Column('phone', String(20), nullable=False),
Column('password', String(25), nullable=False),
Column('created_on', DateTime(), default=datetime.now),
Column('updated_on', DateTime(),
default=datetime.now, onupdate=datetime.now)
)
orders = Table('orders', metadata,
Column('order_id', Integer()),
Column('user_id', ForeignKey('users.user_id')),
Column('shipped', Boolean(), default=False)
)
line_items = Table('line_items', metadata,
Column('line_items_id', Integer(), primary_key=True),
Column('order_id', ForeignKey('orders.order_id')),
Column('cookie_id', ForeignKey('cookies.cookie_id')),
Column('quantity', Integer()),
Column('extended_cost', Numeric(12, 2))
)
engine = create_engine('sqlite:///:memory:')
metadata.create_all(engine)
connection = engine.connect()
from sqlalchemy import select, insert
ins = insert(users).values(
username="cookiemon",
email_address="[email protected]",
phone="111-111-1111",
password="password"
)
result = connection.execute(ins)
s = select([users.c.username])
results = connection.execute(s)
for result in results:
print(result.username)
print(result.password) # AttributeError
IntegratyError異常は、制約に違反した場合に発生します.例えば、一意性の制約に違反するなどです.
s = select([users.c.username])
connection.execute(s).fetchall()
[(u'cookiemon',)]
ins = insert(users).values(
username="cookiemon",
email_address="[email protected]",
phone="111-111-1111",
password="password"
)
result = connection.execute(ins) # IntegrityError, UNIQUE constraint failed: users.username
#
try:
result = connection.execute(ins)
except IntegrityError as error:
print(error.orig.message, error.params)
すべてのSQLAlchemy異常処理方式は上記の考え方であり,[SQLAlchemyError](http://docs.sqlalchemy.org/en/latest/core/exceptions.html)で取得できる情報は次のとおりです.
トランザクションTransactions
from sqlalchemy.exc import IntegrityError
def ship_it(order_id):
s = select([line_items.c.cookie_id, line_items.c.quantity])
s = s.where(line_items.c.order_id == order_id)
transaction = connection.begin() #
cookies_to_ship = connection.execute(s).fetchall()
try:
for cookie in cookies_to_ship:
u = update(cookies).where(cookies.c.cookie_id == cookie.cookie_id)
u = u.values(quantity=cookies.c.quantity - cookie.quantity)
result = connection.execute(u)
u = update(orders).where(orders.c.order_id == order_id)
u = u.values(shipped=True)
result = connection.execute(u)
print("Shipped order ID: {}".format(order_id))
transaction.commit() #
except IntegrityError as error:
transaction.rollback() #
print(error)