python - SQLAlchemy 插入 executemany 函数
问题描述
我正在尝试通过 SQLAlchemy 将字典列表批量插入 MySQL 数据库。在列表中,每个 dict 都有时间和温度。时间值是一个 ISO 时间字符串。我试图让 MySQL 在创建日期时间对象以存储到数据库的过程中使用 STR_TO_DATE 函数。
我已经成功地通过 insert().values({'time':func.STR_TO_DATE(row.time, date_str), 'temp' = row.temp})
示例代码:
import sqlalchemy
from sqlalchemy import create_engine, MetaData, Table, Column, func
from sqlalchemy.dialects.mysql import DATETIME, INTEGER, insert
temp_data = [{'time':'2019-02-07T14:01:00.000000000Z', 'temperature':68},
{'time':'2019-02-07T14:02:00.000000000Z', 'temperature':69},
{'time':'2019-02-07T14:03:00.000000000Z', 'temperature':70},
{'time':'2019-02-07T14:04:00.000000000Z', 'temperature':71}]
date_string = '%Y-%m-%dT%H:%i:%S.%f000Z'
mysql_metadata = MetaData()
mysql_table = Table('temperature', mysql_metadata,
Column('time', DATETIME(fsp = 6), primary_key = True),
Column('temperature', INTEGER()))
def single_insert():
engine = create_engine('mysql://test_user:test@localhost/temperature',
echo = False)
mysql_table.drop(engine, checkfirst = True)
mysql_table.create(engine)
conn = engine.connect()
for row in temp_data:
conn.execute(mysql_table.insert().values(time = func.STR_TO_DATE(row['time'], date_string),
temperature = row['temperature']))
def insert_many():
engine = create_engine('mysql://test_user:test@localhost/temperature',
echo = False)
mysql_table.drop(engine, checkfirst = True)
mysql_table.create(engine)
conn = engine.connect()
conn.execute(mysql_table.insert(), temp_data)
不确定如何通过将参数绑定到可以调用 STR_TO_DATE 的单个输入值来使其工作,以便可以通过字典列表插入数据。
第二次编辑:
这是我的蛮力代码。试图找到一种方法来使用 SQLALchemy Core 来完成这个语句。
def insert_many():
engine = create_engine('mysql://test_user:test@localhost/temperature',
echo = True)
mysql_table.drop(engine, checkfirst = True)
mysql_table.create(engine)
conn = engine.connect()
stmt = text("INSERT INTO temperature VALUES( STR_TO_DATE(:time, '%Y-%m-%dT%H:%i:%S.%f000Z'), :temperature)")
conn.execute(stmt, temp_data)
第三次编辑:
最终想要针对 Python Datetime strptime vs MySQL 方法做一个配置文件。看看哪个更快。
解决方案
对字典列表进行批量插入的一种方法是对每个键使用bindparam并执行执行
from sqlalchemy.sql.expression import bindparam
temp_data = [{'time':'2019-02-07T14:01:00.000000000Z', 'temperature':68},
{'time':'2019-02-07T14:02:00.000000000Z', 'temperature':69},
{'time':'2019-02-07T14:03:00.000000000Z', 'temperature':70},
{'time':'2019-02-07T14:04:00.000000000Z', 'temperature':71}]
def insert_many():
engine = create_engine('mysql://test_user:test@localhost/temperature',
echo = False)
mysql_table.drop(engine, checkfirst = True)
mysql_table.create(engine)
conn = engine.connect()
statement = Mysql_table.insert().values({
'time' : bindparam('time'),
'temperature' : bindparam('temperature')
})
conn.execute(statement, temp_data)
conn.close()
关于 STR_TO_DATE 函数,如何更新字典本身中的这些值,然后执行 insert_many() 函数
for item in temp_data:
item.update((k, func.STR_TO_DATE(v)) for k,v in item.items() if k == 'time')
您始终可以使用时间模块来衡量时间执行
import time
from datetime import datetime
start_time = time.time()
func.STR_TO_DATE('date_value') # datetime.strptime(date_string, "%d %B, %Y")
print('--%s seconds --' %(time.time() - start_time)
推荐阅读
- sql - 属于主表的 SQL 查询列表作为主表上的列
- testing - Jasmine:callThrough 和 callFake
- scala - akka 流 SubFlow 的隐式类(通用路径相关类型)
- python - 如何编辑或自定义用户名字段的必需字符?
- outlook-restapi - 团队会议 blob 或链接被删除
- compilation - 为什么当针对 wasm32 时,clang 会发出 i64 指令?
- javascript - 找不到模块:无法解析“@mui/icons-material/FileDownload”
- html - 查找并列出所有包含 ID 的标题 - jQuery
- jaeger - 如何在 springboot 集成中禁用 INFO jaeger 日志记录条目?
- sql-server - 通过Excel ADODB在sql server中随机“登录超时”