@TOC
to_sql坑
这个坑断断续续搞了我好几天,是数据库连接引起的,特意记下来,以助后来者。 大致步骤: 1.引用pandas和pyodbc 2.conn = pyodbc.connect("DRIVER={ODBC Driver 17 for SQL Server};SERVER=" +host + ";DATABASE=" + db + ";UID=" + user + ";PWD=" +passwd) # 这里是连接mssql,连接变量是conn 3.df = pd.read_sql("select * from test", conn) # 这里能正常读取 3.df.loc[0, 'SendResult']='002' # 将第0行中字段‘SendResult'随便斌一个值,如‘002’ 4.df.to_sql('test',conn,index=False') # 然后写进数据库,坑这时出现了,就是conn导致的,你怎么都没想到,conn在read_sql中能正常读取,在to_sql中却报错。
然后报错: DatabaseError: Execution failed on sql 'SELECT name FROM sqlite_master WHERE type='table' AND name=?;': ('42S02', "[42S02] [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]对象名 'sqlite_master' 无效。 (208) (SQLExecDirectW); [42S02] [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]无法预定义语句 。 (8180)")
解决办法
查了pandas官网和其他不少有关to_sql的文章,都没有看到有提及数据库连接这个坑,不过我注意到,pandas官网的to_sql例子和其他文章的to_sql例子都有一个共同点,就是引用sqlalchemy这个第三方ORM库来进行连接的,然后我依样画葫芦,终于解决to_sql这个报错。
以下是示例代码,并非完整代码,推荐在ipython上单条语句执行。
import pandas as pd
from sqlalchemy import create_engine
con_string = "mssql+pyodbc://" + sql_user + ":" + sql_password + "@" + sql_host + "/" + sql_dbname + "?driver=ODBC+Driver+17+for+SQL+Server"
engine=create_engine(con_string) # 可用于to_sql和read_sql
conn=engine.connect() # 只能用于read_sql,这语句没必要存在,可删除。
df = pd.read_sql("select * from test", engine) # 注意,这里的数据库连接可用conn和engine的
df.loc[0, 'SendResult']='002'
df.to_sql('test',engine,index=False') # 注意,这里的数据库连接只能用engine,不能使用conn
刚刚填了这个坑,特意记下来,应该还有其他解决方法的,望前辈指点。