官方文檔:
- https://docs.sqlalchemy.org/en/14/tutorial/data.html
- https://docs.sqlalchemy.org/en/14/tutorial/data_insert.html
- https://docs.sqlalchemy.org/en/14/tutorial/data_select.html
- https://docs.sqlalchemy.org/en/14/tutorial/data_update.html
本章數(shù)據(jù)庫模型
本節(jié)中的操作將在以下數(shù)據(jù)庫模型里進(jìn)行。
from sqlalchemy import create_engine, MetaData
from sqlalchemy import Table, Column, Integer, String, ForeignKey
engine = create_engine('sqlite:///memory.db', echo=True, future=True)
metadata_obj = MetaData()
user_table = Table(
"user_account",
metadata_obj,
Column('id', Integer, primary_key=True),
Column('name', String(30)),
Column('fullname', String)
)
address_table = Table(
"address",
metadata_obj,
Column('id', Integer, primary_key=True),
Column('user_id', ForeignKey('user_account.id'), nullable=False),
Column('email_address', String, nullable=False)
)
同時(shí)我們會(huì)使用 ORM 來定義數(shù)據(jù)庫模型。
from sqlalchemy import create_engine, MetaData
from sqlalchemy import Table, Column, Integer, String, ForeignKey
from sqlalchemy.orm import declarative_base, relationship
engine = create_engine('sqlite:///memory.db', echo=True, future=True)
Base = declarative_base()
class User(Base):
__tablename__ = 'user_account'
id = Column(Integer, primary_key=True)
name = Column(String(30))
fullname = Column(String)
addresses = relationship("Address", back_populates="user")
def __repr__(self):
return f"User(id={self.id!r}, name={self.name!r}, fullname={self.fullname!r})"
class Address(Base):
__tablename__ = 'address'
id = Column(Integer, primary_key=True)
email_address = Column(String, nullable=False)
user_id = Column(Integer, ForeignKey('user_account.id'))
user = relationship("User", back_populates="addresses")
def __repr__(self):
return f"Address(id={self.id!r}, email_address={self.email_address!r})"
insert() 表達(dá)式
一個(gè) insert() 例子,stmt 變量列明了要插入數(shù)據(jù)的表格和要插入的數(shù)據(jù)。
from sqlalchemy import insert
stmt = insert(user_table).values(name='spongebob', fullname="Spongebob Squarepants")
with engine.connect() as conn:
result = conn.execute(stmt)
conn.commit()
上面的 stmt 變量是一個(gè) Insert 實(shí)例。我們把它字符串化已更好地理解。
>>> print(stmt)
INSERT INTO user_account (name, fullname) VALUES (:name, :fullname)
字符串化是通過一個(gè)數(shù)據(jù)庫對(duì)象編譯形創(chuàng)建的,我們使用 ClauseElement.compile() 獲取這個(gè)對(duì)象;要想查看綁定的參數(shù),可讀取 params 變量。
>>> compiled = stmt.compile()
>>> compiled.params
{'name': 'spongebob', 'fullname': 'Spongebob Squarepants'}
執(zhí)行上述代碼后,會(huì)在指定的數(shù)據(jù)表插入一行數(shù)據(jù),改行數(shù)據(jù)會(huì)被默認(rèn)加上主鍵 id,其值默認(rèn)為 1。我們可以使用 CursorResult.inserted_primary_key 來查看。
>>> result.inserted_primary_key
(1,)
插入多行
with engine.connect() as conn:
result = conn.execute(
insert(user_table),
[
{"name": "sandy", "fullname": "Sandy Cheeks"},
{"name": "patrick", "fullname": "Patrick Star"}
]
)
conn.commit()
使用標(biāo)量子查詢集(scalar subquery)插入
現(xiàn)在我們實(shí)現(xiàn)一個(gè)復(fù)雜點(diǎn)的操作,有下面一組數(shù)據(jù):
[
{"username": 'spongebob', "email_address": "spongebob@sqlalchemy.org"},
{"username": 'sandy', "email_address": "sandy@sqlalchemy.org"},
{"username": 'sandy', "email_address": "sandy@squirrelpower.org"},
]
我們需要在 user_table 數(shù)據(jù)表根據(jù) username 找到對(duì)應(yīng)的行,再把對(duì)應(yīng)的 id 和 email_address 寫入到 address_table 表的 user_id 和 email_address 列中。
from sqlalchemy import create_engine, MetaData
from sqlalchemy import Table, Column, Integer, String, ForeignKey
from sqlalchemy import insert, select, bindparam
engine = create_engine('sqlite:///memory.db', echo=True, future=True)
metadata_obj = MetaData()
user_table = Table(
"user_account",
metadata_obj,
Column('id', Integer, primary_key=True),
Column('name', String(30)),
Column('fullname', String)
)
address_table = Table(
"address",
metadata_obj,
Column('id', Integer, primary_key=True),
Column('user_id', ForeignKey('user_account.id'), nullable=False),
Column('email_address', String, nullable=False)
)
scalar_subq = (
select(user_table.c.id).
where(user_table.c.name==bindparam('username')).
scalar_subquery()
)
with engine.connect() as conn:
result = conn.execute(
insert(address_table).values(user_id=scalar_subq),
[
{"username": 'spongebob', "email_address": "spongebob@sqlalchemy.org"},
{"username": 'sandy', "email_address": "sandy@sqlalchemy.org"},
{"username": 'sandy', "email_address": "sandy@squirrelpower.org"},
]
)
conn.commit()
select() 表達(dá)式
我們使用 select() 表達(dá)式進(jìn)行 SQL 的查詢操作;我們把語句字符串化,讓它更好理解。
from sqlalchemy import select
stmt = select(user_table).where(user_table.c.name == 'spongebob')
print(stmt)
# 輸出結(jié)果:
SELECT user_account.id, user_account.name, user_account.fullname
FROM user_account
WHERE user_account.name = :name_1
現(xiàn)在我們執(zhí)行這個(gè)查詢語句。
from sqlalchemy import select
stmt = select(user_table).where(user_table.c.name == 'spongebob')
with engine.connect() as conn:
for row in conn.execute(stmt):
print(row)
# 輸出結(jié)果:
FROM user_account
WHERE user_account.name = ?
2022-03-22 11:02:50,869 INFO sqlalchemy.engine.Engine [generated in 0.00171s] ('spongebob',)
(1, 'spongebob', 'Spongebob Squarepants')
2022-03-22 11:02:50,902 INFO sqlalchemy.engine.Engine ROLLBACK
當(dāng)我們使用 ORM 方法定義數(shù)據(jù)庫對(duì)象的時(shí)候,我們更適合的方式是使用 Session.execute() 來執(zhí)行語句。
from sqlalchemy.orm import Session
from sqlalchemy import select
stmt = select(User).where(User.name == 'spongebob')
with Session(engine) as session:
for row in session.execute(stmt):
print(row)
# 輸出結(jié)果
FROM user_account
WHERE user_account.name = ?
INFO sqlalchemy.engine.Engine [generated in 0.00102s] ('spongebob',)
(User(id=1, name='spongebob', fullname='Spongebob Squarepants'),)
INFO sqlalchemy.engine.Engine ROLLBACK
兩種方法有什么區(qū)別呢,我們把它字符串化打印出來。
>>> print(select(user_table))
SELECT user_account.id, user_account.name, user_account.fullname
FROM user_account
>>> print(select(User))
SELECT user_account.id, user_account.name, user_account.fullname
FROM user_account
可見二者是等價(jià)的。如果要訪問表的某個(gè)列對(duì)象,我們?cè)趺醋瞿兀?/p>
>>> print(select(user_table.c.id))
SELECT user_account.id
FROM user_account
>>> print(select(User.id))
SELECT user_account.id
FROM user_account
可見前一種方法要使用 Table.c 方法來訪問,后一種方法可以直接訪問屬性名。
以對(duì)象方式顯示查詢結(jié)果
當(dāng)使用 ORM 方式時(shí),我們希望數(shù)據(jù)庫中的一行能被封裝為一個(gè) Python 對(duì)象。
from sqlalchemy.orm import Session
from sqlalchemy import select
with Session(engine) as session:
row = session.execute(select(User)).first()
print(row)
# 輸出結(jié)果:
(User(id=1, name='spongebob', fullname='Spongebob Squarepants'),)
上例中,我們選擇了 user_account 的第一行,并根據(jù)改行的數(shù)據(jù)封裝成一個(gè) User 對(duì)象;注意,row 現(xiàn)在是一個(gè)元組。
>>> row[0]
User(id=1, name='spongebob', fullname='Spongebob Squarepants')
另一個(gè)方法是使用 session.scalars 方法來執(zhí)行語句。
with Session(engine) as session:
user = session.scalars(select(User)).first()
print(user)
也可以直接獲取行的某個(gè)數(shù)值而不返回一個(gè) User 對(duì)象。
with Session(engine) as session:
row = session.execute(select(User.name, User.fullname)).first()
print(row)
# 輸出結(jié)果:
('spongebob', 'Spongebob Squarepants')
多重查詢條件
with Session(engine) as session:
row = session.execute(
select(User.name, Address).
where(User.id==Address.user_id).
order_by(Address.id)
).all()
print(row)
# 輸出結(jié)果:
[('spongebob', Address(id=1, email_address='spongebob@sqlalchemy.org')),
('sandy', Address(id=2, email_address='sandy@sqlalchemy.org')),
('sandy', Address(id=3, email_address='sandy@squirrelpower.org'))]
上例中的查詢相當(dāng)于:
SELECT user_account.name, address.id, address.email_address, address.user_id
FROM user_account, address
WHERE user_account.id = address.user_id ORDER BY address.id
label 方法
ColumnElement.label() 方法可以為查詢結(jié)果設(shè)定一個(gè)“別名”,然后在其他地方調(diào)用。
with Session(engine) as session:
stmt = (
select(
("Username: " + user_table.c.name).label("username"),
).order_by(user_table.c.name)
)
for row in session.execute(stmt):
print(f"{row.username}")
# 輸出結(jié)果:
Username: patrick
Username: sandy
Username: spongebob
text 方法和 literal_column 方法
text() 方法可以在 select() 表達(dá)式中增加一個(gè)自定義的字符串作為列對(duì)象。
from sqlalchemy import select, text
stmt = (
select(
text("'some phrase'"), user_table.c.name
).order_by(user_table.c.name)
)
with engine.connect() as conn:
print(conn.execute(stmt).all())
# 輸出結(jié)果:
[('some phrase', 'patrick'), ('some phrase', 'sandy'), ('some phrase', 'spongebob')]
如果想把這種自定義的字符串和 label() 方法結(jié)合一起使用,可以用 literal_column() 方法實(shí)施。
from sqlalchemy import literal_column
stmt = (
select(
literal_column("'some phrase'").label("p"), user_table.c.name
).order_by(user_table.c.name)
)
with engine.connect() as conn:
for row in conn.execute(stmt):
print(f"{row.p}, {row.name}")
# 輸出結(jié)果:
some phrase, patrick
some phrase, sandy
some phrase, spongebob
where 字句
where 子句用于使用查詢條件,大多數(shù) Python 運(yùn)算符,如 ==、!=、<、>=等都支持。
>>> print(user_table.c.name == 'squidward')
user_account.name = :name_1
>>> print(address_table.c.user_id > 10)
address.user_id > :user_id_1
把 select 方法和 where 字句結(jié)合使用。
>>> print(select(user_table).where(user_table.c.name == 'squidward'))
SELECT user_account.id, user_account.name, user_account.fullname
FROM user_account
WHERE user_account.name = :name_1
多個(gè) where 子句可以并列使用,產(chǎn)生 AND 的效果。
print(
select(address_table.c.email_address).
where(user_table.c.name == 'squidward').
where(address_table.c.user_id == user_table.c.id)
)
# 輸出結(jié)果:
SELECT address.email_address
FROM address, user_account
WHERE user_account.name = :name_1 AND address.user_id = user_account.id
另一種寫法:
print(
select(address_table.c.email_address).
where(
user_table.c.name == 'squidward',
address_table.c.user_id == user_table.c.id
)
)
AND 和 OR 表達(dá)式可以使用 sqlalchemy 的 and_() 與 or_() 方法來實(shí)現(xiàn)。
from sqlalchemy import and_, or_
print(
select(Address.email_address).
where(
and_(
or_(User.name == 'squidward', User.name == 'sandy'),
Address.user_id == User.id
)
)
)
# 輸出結(jié)果:
SELECT address.email_address
FROM address, user_account
WHERE (user_account.name = :name_1 OR user_account.name = :name_2) AND address.user_id = user_account.id
當(dāng)我們使用 ORM 定義數(shù)據(jù)庫時(shí),還有一個(gè)簡單的查詢方法,就是使用 Select.filter_by() 方法。
print(
select(User).filter_by(name='spongebob', fullname='Spongebob Squarepants')
)
# 輸出結(jié)果:
SELECT user_account.id, user_account.name, user_account.fullname
FROM user_account
WHERE user_account.name = :name_1 AND user_account.fullname = :fullname_1
join 子句
要在 sqlalchemy 實(shí)現(xiàn) JOIN 操作(JOIN 的具體含義見:SQL - JOIN
),一種方式是使用 Select.join_from()。
print(
select(user_table.c.name, address_table.c.email_address).
join_from(user_table, address_table)
)
# 輸出結(jié)果:
SELECT user_account.name, address.email_address
FROM user_account JOIN address ON user_account.id = address.user_id
另一種方式是使用 Select.join() 方法。
print(
select(user_table.c.name, address_table.c.email_address).
join(address_table)
)
# 輸出結(jié)果:
SELECT user_account.name, address.email_address
FROM user_account JOIN address ON user_account.id = address.user_id
使用 join() 時(shí)候也可以把左表和右表的關(guān)系都寫清楚。
print(
select(user_table.c.name, address_table.c.email_address).
select_from(user_table).join(address_table)
)
那么使用 join() 的時(shí)候, sqlalchemy 怎么知道我們連接兩表的條件是 user_account.id = address.user_id 的呢?這是因?yàn)槲覀兊臄?shù)據(jù)庫模型設(shè)定了外鍵:ForeignKey('user_account.id')。
如果沒有在數(shù)據(jù)庫模型中設(shè)定外鍵,可以給 join() 方法額外添加一個(gè)參數(shù)來起到 ON 子句的作用。
print(
select(address_table.c.email_address).
select_from(user_table).
join(address_table, user_table.c.id == address_table.c.user_id)
)
LEFT OUTER JOIN 與 FULL OUTER JOIN
當(dāng)使用 join_from() 或 join() 方法時(shí)候默認(rèn)為 INNER JOIN,如果使用 LEFT OUTER JOIN 與 FULL OUTER JOIN 時(shí),可以帶上 Select.join.isouter 和 Select.join.full 參數(shù)。
print(
select(user_table).join(address_table, isouter=True)
)
# 輸出結(jié)果:
SELECT user_account.id, user_account.name, user_account.fullname
FROM user_account LEFT OUTER JOIN address ON user_account.id = address.user_id
print(
select(user_table).join(address_table, full=True)
)
# 輸出結(jié)果:
SELECT user_account.id, user_account.name, user_account.fullname
FROM user_account FULL OUTER JOIN address ON user_account.id = address.user_id
還有一個(gè) Select.outerjoin() 方法可以實(shí)現(xiàn) LEFT OUTER JOIN。
print(
select(user_table).outerjoin(address_table)
)
# 輸出結(jié)果:
SELECT user_account.id, user_account.name, user_account.fullname
FROM user_account LEFT OUTER JOIN address ON user_account.id = address.user_id
注意:SQL 還有一個(gè) RIGHT OUTER JOIN 的子句,但 sqlalchemy 并不直接使用它,要達(dá)到該效果可以把左右表調(diào)轉(zhuǎn)位置后再使用 LEFT OUTER JOIN。
ORDER BY, GROUP BY, HAVING 子句
ORDER BY
使用 Select.order_by() 方法來實(shí)現(xiàn) ORDER BY 子句的功能。
print(select(user_table).order_by(user_table.c.name))
# 輸出結(jié)果:
SELECT user_account.id, user_account.name, user_account.fullname
FROM user_account ORDER BY user_account.name
要使用升序或降序來排序可以使用 ColumnElement.asc() 和 ColumnElement.desc()。
print(select(user_table).order_by(user_table.c.fullname.desc()))
# 輸出結(jié)果:
SELECT user_account.id, user_account.name, user_account.fullname
FROM user_account ORDER BY user_account.fullname DESC
使用 GROUP BY, HAVING 的聚合函數(shù)
在 SQL 中,聚合函數(shù)(aggregate functions)允許將多行的列表達(dá)式聚合在一起,產(chǎn)生一個(gè)單一的結(jié)果。比如:計(jì)算數(shù)量、計(jì)算平均數(shù)、最大值、最小值等。
>>> from sqlalchemy import func
>>> count_fn = func.count(user_table.c.id)
>>> print(count_fn)
count(user_account.id)
使用聚合函數(shù)時(shí),GROUP BY 子句定義了分組的依據(jù),HAVING 子句的使用方式與 WHERE 子句類似,用于定義過濾的條件。
SQLAlchemy 使用 Select.group_by() 和 Select.having() 方法來實(shí)現(xiàn) GROUP BY 子句和 HAVING 子句。
下面來看一個(gè)例子:
from sqlalchemy import select, func
with engine.connect() as conn:
result = conn.execute(
select(User.name, func.count(Address.id).label("count")).
join(Address).
group_by(User.name).
having(func.count(Address.id) > 1)
)
print(result.all())
# 查詢結(jié)果:
[('sandy', 2)]
這等價(jià)于這樣的 SQL 語句。
SELECT user_account.name, count(address.id) AS count
FROM user_account JOIN address
ON user_account.id = address.user_id
GROUP BY user_account.name
HAVING count(address.id) > 1
對(duì)聚合結(jié)果排序
使用聚合函數(shù)后會(huì)產(chǎn)生一個(gè)或多個(gè)新的列,我們可以對(duì)這些新產(chǎn)生的列進(jìn)行排序操作,使用 label 方法給它們加上自定義的名字會(huì)更方便。
stmt = select(
Address.user_id,
func.count(Address.id).label('num_addresses')).\
group_by("user_id").order_by("user_id", desc("num_addresses")
)
print(stmt)
# 輸出結(jié)果:
SELECT address.user_id, count(address.id) AS num_addresses
FROM address GROUP BY address.user_id ORDER BY address.user_id, num_addresses DESC
使用別名(alias)
有時(shí)候我們需要對(duì)同一個(gè)表的同一列作多次引用,這時(shí)候我們就需要使用 SQL 的 AS 子句對(duì)該列定一個(gè)“別名”。sqlalchemy 中我們使用 FromClause.alias() 方法來實(shí)現(xiàn)。
user_alias_1 = user_table.alias()
user_alias_2 = user_table.alias()
print(
select(user_alias_1.c.name, user_alias_2.c.name).
join_from(user_alias_1, user_alias_2, user_alias_1.c.id > user_alias_2.c.id)
)
# 輸出結(jié)果:
SELECT user_account_1.name, user_account_2.name AS name_1
FROM user_account AS user_account_1
JOIN user_account AS user_account_2 ON user_account_1.id > user_account_2.id
ORM 下的別名
使用 ORM 時(shí)我們用 aliased() 來定義別名。
from sqlalchemy.orm import aliased
address_alias_1 = aliased(Address)
address_alias_2 = aliased(Address)
print(
select(User).
join_from(User, address_alias_1).
where(address_alias_1.email_address == 'patrick@aol.com').
join_from(User, address_alias_2).
where(address_alias_2.email_address == 'patrick@gmail.com')
)
# 輸出結(jié)果:
SELECT user_account.id, user_account.name, user_account.fullname
FROM user_account
JOIN address AS address_1 ON user_account.id = address_1.user_id
JOIN address AS address_2 ON user_account.id = address_2.user_id
WHERE address_1.email_address = :email_address_1 AND address_2.email_address = :email_address_2
子查詢(Subqueries)
SQL 中的子查詢是一個(gè) SELECT 語句,它被放在括號(hào)中,并被放在一個(gè)包圍語句的上下文中,在 sqlalchemy 中我們使用 Select.subquery() 方法來表示子查詢。
下面我們看一個(gè)使用子查詢的例子。
先構(gòu)建一個(gè)子查詢語句 subp:
subq = select(
func.count(address_table.c.id).label("count"),
address_table.c.user_id
).group_by(address_table.c.user_id).subquery()
將他打印出來,會(huì)發(fā)現(xiàn)它只是普通的 SQL SELECT 語句,要讓它發(fā)揮子查詢的作用還需要嵌套到其他語句中使用。
>>> print(subq)
SELECT count(address.id) AS count, address.user_id
FROM address GROUP BY address.user_id
子查詢對(duì)象 subp 實(shí)質(zhì)上是一個(gè) FROM 對(duì)象,我們可以使用 Subquery.c 的形式讀取其參數(shù)。
>>> print(subq.c.count)
anon_1.count
最后,我們把子查詢嵌套到一個(gè)更大的 SELECT 查詢中。
subq = select(
func.count(address_table.c.id).label("count"),
address_table.c.user_id
).group_by(address_table.c.user_id).subquery()
stmt = select(
user_table.c.name,
user_table.c.fullname,
subq.c.count
).join_from(user_table, subq)
>>> print(stmt)
SELECT user_account.name, user_account.fullname, anon_1.count
FROM user_account JOIN (SELECT count(address.id) AS count, address.user_id AS user_id
FROM address GROUP BY address.user_id) AS anon_1 ON user_account.id = anon_1.user_id
普通表表達(dá)式(CTE)
在 SQLAlchemy 中,普通表表達(dá)式(Common Table Expressions)的結(jié)構(gòu)和使用方式與子查詢幾乎相同。使用 Select.cte() 調(diào)用。
使用 CTEs 的例子。
subq = select(
func.count(address_table.c.id).label("count"),
address_table.c.user_id
).group_by(address_table.c.user_id).cte()
stmt = select(
user_table.c.name,
user_table.c.fullname,
subq.c.count
).join_from(user_table, subq)
>>> print(stmt)
WITH anon_1 AS
(SELECT count(address.id) AS count, address.user_id AS user_id
FROM address GROUP BY address.user_id)
SELECT user_account.name, user_account.fullname, anon_1.count
FROM user_account JOIN anon_1 ON user_account.id = anon_1.user_id
ORM 下使用子查詢
subq = select(
func.count(Address.id).label("count"),
Address.user_id
).group_by(Address.user_id).subquery()
stmt = select(
User.name,
User.fullname,
subq.c.count
).join_from(User, subq)
合并 (UNION)
在 SQL 中,SELECT 語句可以通過 UNION 或 UNION ALL 合并查詢結(jié)果,產(chǎn)生由一個(gè)或多個(gè)語句共同產(chǎn)生的所有記錄的集合。在 SQLAlchemy 中我們使用 union() 或 union_all() 來實(shí)現(xiàn)同樣的效果。
from sqlalchemy import union_all
stmt1 = select(user_table).where(user_table.c.name == 'sandy')
stmt2 = select(user_table).where(user_table.c.name == 'spongebob')
u = union_all(stmt1, stmt2)
with engine.connect() as conn:
result = conn.execute(u)
print(result.all())
# 輸出結(jié)果:
BEGIN (implicit)
SELECT user_account.id, user_account.name, user_account.fullname
FROM user_account
WHERE user_account.name = ?
UNION ALL SELECT user_account.id, user_account.name, user_account.fullname
FROM user_account
WHERE user_account.name = ?
[generated in ...] ('sandy', 'spongebob')
[(2, 'sandy', 'Sandy Cheeks'), (1, 'spongebob', 'Spongebob Squarepants')]
ROLLBACK
update() 表達(dá)式
update() 函數(shù)生成一個(gè)新的 Update 實(shí)例,代表 SQL 中的 UPDATE 語句,它將更新一個(gè)表中的現(xiàn)有數(shù)據(jù)。
一個(gè)基本的 update() 函數(shù)例子:
from sqlalchemy import update
stmt = (
update(user_table).where(user_table.c.name == 'patrick').
values(fullname='Patrick the Star')
)
print(stmt)
# 輸出結(jié)果:
UPDATE user_account SET fullname=:fullname WHERE user_account.name = :name_1
Update.values() 方法控制 UPDATE 語句中 SET 子句的內(nèi)容;它也能接受表達(dá)式作為參數(shù)。
stmt = (
update(user_table).
values(fullname="Username: " + user_table.c.name)
)
print(stmt)
# 輸出結(jié)果:
UPDATE user_account SET fullname=(:name_1 || user_account.name)
使用 bindparam 的數(shù)據(jù)修改
現(xiàn)在我們來完成一組復(fù)雜點(diǎn)的修改,有這么一組數(shù)據(jù):
[
{'oldname':'spongebob', 'newname':'ed'},
{'oldname':'sandy', 'newname':'mary'},
{'oldname':'patrick', 'newname':'jake'},
]
我們需要將 user_table 表的 name 字段和上述數(shù)據(jù)中的 oldname 字段來匹配,把 name 字段的內(nèi)容修改為對(duì)應(yīng)的 newname;這時(shí)候我們需要用到 bindparam() 方法。
from sqlalchemy import bindparam
stmt = (
update(user_table).
where(user_table.c.name == bindparam('oldname')).
values(name=bindparam('newname'))
)
with engine.begin() as conn:
conn.execute(
stmt,
[
{'oldname':'spongebob', 'newname':'ed'},
{'oldname':'sandy', 'newname':'mary'},
{'oldname':'patrick', 'newname':'jake'},
]
)
conn.commit()
# 輸出結(jié)果:
BEGIN (implicit)
UPDATE user_account SET name=? WHERE user_account.name = ?
[generated in 0.00089s] (('ed', 'spongebob'), ('mary', 'sandy'), ('jake', 'patrick'))
COMMIT
delete() 表達(dá)式
delete() 函數(shù)生成一個(gè) Delete 實(shí)例,代表 SQL 中的 DELETE 語句,用于從表中刪除記錄。從 API 的角度看,delete() 語句與 update() 結(jié)構(gòu)非常相似,傳統(tǒng)上不返回記錄。
一個(gè) delete() 函數(shù)的例子:
from sqlalchemy import delete
stmt = delete(user_table).where(user_table.c.name == 'patrick')
print(stmt)
# 輸出結(jié)果:
DELETE FROM user_account WHERE user_account.name = :name_1