3. 數(shù)據(jù)操作

官方文檔:






本章數(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)的 idemail_address 寫入到 address_table 表的 user_idemail_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
    )
)

ANDOR 表達(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 JOINFULL OUTER JOIN 時(shí),可以帶上 Select.join.isouterSelect.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 語句可以通過 UNIONUNION 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
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容