官方文檔:
- https://docs.sqlalchemy.org/en/14/tutorial/engine.html
- https://docs.sqlalchemy.org/en/14/tutorial/dbapi_transactions.html
引擎(Engine)
創(chuàng)建任何 SQLAlchemy 應(yīng)用程序,都需要先創(chuàng)建一個引擎(Engine)對象。該對象作為連接到特定數(shù)據(jù)庫的中心源,為這些數(shù)據(jù)庫連接提供一個工廠和一個稱為連接池的保存空間。
引擎通常是一個全局對象,只為特定的數(shù)據(jù)庫服務(wù)器創(chuàng)建一次,并使用一個 URL 字符串進行配置,描述它應(yīng)該如何連接到數(shù)據(jù)庫主機或后端。
在本教程中,我們將使用一個 SQLite 數(shù)據(jù)庫。這是一種簡單的測試方法,不需要預(yù)先設(shè)置一個實際存在的數(shù)據(jù)庫。引擎是通過使用 create_engine() 方法創(chuàng)建的,指定 create_engine.future 參數(shù)為 True,這樣我們就可以完全使用 2.0 風(fēng)格的語法。
from sqlalchemy import create_engine
engine = create_engine('sqlite+pysqlite:///memory.db', echo=True, future=True)
create_engine() 方法的主要參數(shù)是一個字符串 URL,它定義了以下信息:
定義了要鏈接的數(shù)據(jù)庫類型,本例是
sqlite。定義了使用什么 DBAPI,Python DBAPI 是一個第三方驅(qū)動,SQLAlchemy 用它來與一個特定的數(shù)據(jù)庫進行交互,本例中使用的是
pysqlite。
3.數(shù)據(jù)庫存放的位置,本例中使用相對路徑,將在根目錄中創(chuàng)建 memory.db 數(shù)據(jù)庫文件。
我們還指定了一個參數(shù) create_engine.echo 為 True,它會使標準 SQL 語句在終端中輸出。
建立連接(Connection)
從面向用戶的角度來看,引擎對象的唯一目的是提供一個與數(shù)據(jù)庫的連接單元,稱為 Connection。
我們的教程還沒進入到 ORM 部分,所以下面例子中我們依然使用原生 SQL 語句(textual SQL)來操作數(shù)據(jù)庫,text 方法可以讓鏈接對象接受原生 SQL 語句。
下面是一個創(chuàng)建數(shù)據(jù)庫鏈接,創(chuàng)建數(shù)據(jù)表(Table),并插入數(shù)據(jù)的例子。
from sqlalchemy import create_engine, text
engine = create_engine('sqlite+pysqlite:///memory.db', echo=True, future=True)
with engine.connect() as conn:
conn.execute(text("CREATE TABLE some_table (x int, y int)"))
conn.execute(
text("INSERT INTO some_table (x, y) VALUES (:x, :y)"),
[{"x": 1, "y": 1}, {"x": 2, "y": 4}]
)
conn.commit()
執(zhí)行上述代碼后,會在根目錄創(chuàng)建 memory.db 數(shù)據(jù)庫文件;CREATE TABLE 語句會新建 some_table 表;INSERT 語句定義了如何插入數(shù)據(jù);Connection.commit() 方法提交上述對數(shù)據(jù)庫的操作語句。
除了使用 commit 方法來提交改變之外,還可以使用 Engine.begin() 方法。
with engine.begin() as conn:
conn.execute(text("CREATE TABLE some_table (x int, y int)"))
conn.execute(text(
"INSERT INTO some_table (x, y) VALUES (:x, :y)"),
[{"x": 1, "y": 1}, {"x": 2, "y": 4}]
)
再看一個用 select 語句執(zhí)行查找的例子:
with engine.connect() as conn:
result = conn.execute(text("SELECT x, y FROM some_table"))
for row in result:
print(f"x: {row.x} y: {row.y}")
輸出:
x: 1 y: 1
x: 2 y: 4
使用參數(shù)
使用冒號來標記參數(shù),本例中是 :y;將篩選出 y 小于 2 的行。
with engine.connect() as conn:
result = conn.execute(
text("SELECT x, y FROM some_table WHERE y < :y"),
{"y": 2}
)
for row in result:
print(f"x: {row.x} y: {row.y}")
使用多個參數(shù)
with engine.connect() as conn:
conn.execute(
text("INSERT INTO some_table (x, y) VALUES (:x, :y)"),
[{"x": 11, "y": 12}, {"x": 13, "y": 14}]
)
conn.commit()
把參數(shù)和語句綁定
stmt = text("SELECT x, y FROM some_table WHERE y > :y ORDER BY x, y").bindparams(y=2)
with engine.connect() as conn:
result = conn.execute(stmt)
for row in result:
print(f"x: {row.x} y: {row.y}")
使用 Session
上面舉得使用 Connection 的例子在 ORM 中也能適用,但我們習(xí)慣上更多使用 Session。當(dāng)使用 ORM 時,基本的數(shù)據(jù)庫交互對象被稱為 Session。在 SQLAlchemy 中,該對象的使用方式與 Connection 非常相似,事實上,在使用 Session 時,它在內(nèi)部指的是 Connection。
from sqlalchemy import create_engine, text
from sqlalchemy.orm import Session
stmt = text("SELECT x, y FROM some_table WHERE y > :y ORDER BY x, y").bindparams(y=2)
with Session(engine) as session:
result = session.execute(stmt)
for row in result:
print(f"x: {row.x} y: {row.y}")