sqlalchemy 实现 mysql INSERT INTO...ON DUPLICATE KEY UPDATE语法

发布时间 2023-12-11 10:53:42作者: 大师兄啊哈

1. 前言

myql的INSERT INTO...ON DUPLICATE KEY UPDATE语句,简单点来说,就是如果记录不存在,则插入,如果记录存在,则更新。

那怎么判断记录存在否?—— 主键、唯一键。

那不是可以使用replace语句吗?—— 原理上可以,但是sqlalchemy orm中的的实现,是使用merge语法,这个语法有一个限制,就是判断是否已经存在记录的时候,只检查主键,不检查唯一键。

因此使用sqlalchemy中对INSERT INTO...ON DUPLICATE KEY UPDATE的实现。

2. 实现

官网给的例子[1]:

from sqlalchemy.dialects.mysql import insert

insert_stmt = insert(my_table).values(
     id='some_existing_id',
     data='inserted value')
 
on_duplicate_key_stmt = insert_stmt.on_duplicate_key_update(
     data=insert_stmt.inserted.data,
     status='U'
)
print(on_duplicate_key_stmt)
conn.execute(on_duplicate_key_stmt)

是不是很迷,整体来说sqlalchemy给的文档都比较迷,解释一下:

  • insert(my_table):table表示你orm中定义的关于表的model类,譬如你有个test的表,里面只有四个字段,id,a,b,c,你orm中定义的model类如下:
 1 from sqlalchemy.ext.declarative import declarative_base
 2 Base = declarative_base()
 3 
 4 class Test(Base):
 5     __tablename__ = "test"
 6     id = Column(Integer, primary_key=True, index=True)
 7     a = Column(Integer) 
 8     b = Column(String(36)) 
 9     c = Column(String(50)) 
10 
11     __table_args__ = (
12         UniqueConstraint("b", "c", name='uni_bc'),
13     )

可以看到,主键为id,另外b_c构成一个联合唯一键。

  • insert(my_table).values:后面的参数表示插入的数据(key value),如
insert_stmt = insert(Test).values(
     a=1,
     b='newb',
     c='newc')
  • insert_stmt.on_duplicate_key_update表示如果记录存在,需要更新那些字段,键值对的规则如上:
on_duplicate_key_stmt = insert_stmt.on_duplicate_key_update(
     c='newerc')
  • conn.execute(on_duplicate_key_stmt):conn为你的db 连接会话。

当然,大部分时候,你不想手动指定每个字段,而是将所有需要插入的字段都放在dict中,如果不存在则插入,存在则更新,则直接使用Python的解包语法糖即可:

new_record = {
    a = 1, 
    b = 'newb',
    c = 'newc'
}

insert_stmt = insert(Test).values(**new_record)

on_duplicate_key_stmt = insert_stmt.on_duplicate_key_update(**new_record)

conn.execute(on_duplicate_key_stmt)

基本就是实现replace into的效果了,如果有其他方法的朋友请不吝留言。

3. 参考

[1] INSERT…ON DUPLICATE KEY UPDATE (Upsert)

(完)