python3pandasto_sql填坑

更新时间:2023-05-11 02:53:13 阅读: 评论:0

python3pandasto_sql填坑
今天在使⽤pandas的to_sql⽅法时,遇到⼀堆问题,各种百度⾕歌,真正靠谱的答案少之⼜少,真不知道那些⽂章的作者有没有运⾏过他⽂章中的代码特在此做⼀个梳理。
为什么要使⽤to_sql⽅法
表结构如下:
CREATE TABLE `my_balance` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`balance` decimal(20,4) NOT NULL COMMENT '余额',
`account` varchar(30) DEFAULT NULL COMMENT '账户',
`charges` decimal(10,4) NOT NULL COMMENT '交易⼿续费/每笔',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COMMENT='账户表'
现在要向my_balance表中插⼊⼀下数据,下⾯我们来看三段代码:
1. 普通pymysql sql inrt 写法(强烈不推介这种写法)
import pymysql.cursors
# 建⽴数据库连接
db = t(host='127.0.0.1', ur='root',
passwd='root', db='tushare', chart='utf8')
balance =11500.0000
account =8888
charges =0.0005
# inrt 语句
sql = f"inrt into `tushare`.`my_balance` ( `balance`, `account`, `charges`) values ( '{balance}', '{account}', '{charges}')"
# 执⾏新增或更新数据操作,返回受影响的⾏数
cursor = db.cursor()
res_row = ute(sql)
# 提交事务
# 关闭链接
db.clo()
优点:代码⽐较直观易懂,适合初学者读
缺点:每次⼀个inrt语句都要复制⼀堆代码,代码复⽤性为0.
2. pandas拼接inrt写法(这种写法有BUG)
import pandas as pd
import pymysql.cursors
def init_db():
# 建⽴数据库连接
db = t(host='127.0.0.1', ur='root',
passwd='root', db='tushare', chart='utf8')
return db
def inrt_data_pandasType(table_name, valus, db):
'''
向数据库中新增数据
table_name:库名
valus:字段名称和对应数据,组成的数组
'''
pop = pd.Series(valus)
into =','.join(pop.keys().values)
val =','.join(str(v)for v in pop.values)
sql = f"inrt into {table_name}({into}) values({val})"
cursor = db.cursor()
ute(sql)
# 执⾏SQL
db = init_db()
values ={'balance':11400.0000,'account':'8866.ZH','charges':0.0005}
inrt_data_pandasType('my_balance', values, db)
db.clo()
'account': '8866.ZH'问题出在这⾥,错误如下:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL rver version for the right syntax to u near 'ZH,0.0005)
所以只能存储没带标点符号的字符串~!
so,优缺点就不说了,这BUG太明显,压根不能⽤~!
4. to_sql写法
import pandas as pd
from sqlalchemy import create_engine
engine = create_engine(
"mysql+pymysql://root:root@localhost:3306/tushare?chart=utf8")
df = pd.DataFrame({'balance':[10000.000],'account':
['13579.SH'],'charges':[0.0005]})
<_sql(name='my_balance', con=engine, if_exists='append',
index=Fal, index_label='id')
你没有看错,就这么⼏⾏就搞定了inrt了,是不是⾮常爽~!但是有⼏点需要注意下:
错误信息:Execution failed on sql ‘SELECT name FROM sqlite_master WHERE type=‘table’ AND name=?;’: not all arguments converted during string formatting
数据库链接不再使⽤pymysql,⽽改⽤sqlalchemy,con=engine ⽽不是con=db
最最最坑的地⽅出现了,⼤家注意:
错误:No module named ‘MySQLdb’
百度到的代码,基本99%都是这么写的:
mysql+mysqldb://root:root@localhost:3306/tushare?chart=utf8
但是,如果按照如上写法,在python3.6(我的python版本)环境下会出现找不到mysqldb模块错误!
正确的写法如下,因为python3将mysqldb改为pymysql了
mysql+pymysql://root:root@localhost:3306/tushare?chart=utf8
if_exists 的参数说明
fail的意思如果表存在,啥也不做
replace的意思,如果表存在,删了表,再建⽴⼀个新表,把数据插⼊
append的意思,如果表存在,把数据插⼊,如果表不存在创建⼀个表!!
index=Fal, index_label=‘id’
如果你数据库中主键名称为index则不⽤设置这两项,如果不是,请按照主键名称设置!
附上⼀篇⽂章:
关于to_sql事务问题
看到这⾥,有编程经验的朋友,⼀定会发现,使⽤to_sql的代码中,没有看到事务,在有多个inrt或者update的情况时,如果回滚提交呢?从下⾯这篇⽂章中寻找答案吧~!
不能翻墙的⼩伙伴请看下⾯代码⽰例:
engine = create_engine(
"mysql+pymysql://root:root@localhost:3306/tushare?chart=utf8")
df = pd.DataFrame({'balance':[10000.000],'account':
['13579.SH'],'charges':[0.0005]})
df1 = pd.DataFrame({'balance':[1234.000],'account':
['17886.SH'],'charges':[0.0005]})
# 开始事物
with engine.begin()as conn:
<_sql(name='my_balance', con=conn, if_exists='append',
index=Fal, index_label='id')
# 故意出现错误的代码,测试事物回滚
<_sql(name='my_balance', con=conn, if_exists='append')

本文发布于:2023-05-11 02:53:13,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/82/579666.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:代码   数据   数据库   写法
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图