pandas +sqlalchemy读写oracle数据库

pandas的DataFrame是常用的数据分析数据格式,Oracle数据库是常用的结构化数据存储方式,通常做数据分析牵涉到大量的数据时,我们必须通过借助一定的工具进行,而不能单单依靠excel,因此通过pandas进行数据分析,以Oracle作为存储数据的媒介便成为了我们最方便或者灵活的选择,同时DataFrame的数据格式样式和oracle的结构化表非常的相似,将DataFrame格式的数据直接写入oracle以及将oracle的数据表直接读取为DataFrame便极大的简化了数据格式转换的工作,非常的方便。

本次我们通过sqlalchemy库登录oracle,通过pandas的相关函数和方式实现数据的增删改查。

登录oracle

首先先导入sqlalchemy库的create_engine,

通过 engine = create_engine("dialect+driver://username:password@host:port/database")初始化连接

参数说明:

dialect,是数据库类型包括:sqlite, mysql, postgresql, oracle,  mssql等
driver,指定连接数据库的API,如:`psycopg2``, ``pyodbc``, ``cx_oracle``等,为可选关键字。
username,用户名
password,密码
host,网络地址,可以用ip,域名,计算机名,当然是你能访问到的。
port,数据库端口。
database,数据库名称。

例如建立mysql的连接方式为:(echo=True,会显示在加载数据库所执行的SQL语句,可不选此参数,默认为False)

engine = create_engine("mysql://scott:tiger@hostname/dbname",encoding='utf-8', echo=True)

建立oracle的连接方式为:

engine = create_engine("oracle://scott:tiger@hostname/dbname",encoding='utf-8', echo=True)

from sqlalchemy import   create_engine 
engine = create_engine("oracle://scott:tiger@hostname/dbname",encoding='utf-8', echo=True)

由此,我们便初始化了数据库的连接,也就是说已经登录了数据库

增删改查

我们用pandas的read_sql方法实现数据库的查询、删除、更新操作,用to_sql方法实现数据的写入。

read_sql

首先看read_sql官方介绍:pd.read_sql(sql, con, index_col=None, coerce_float=True, params=None, parse_dates=None, columns=None, chunksize=None)

参数说明:

sql,执行的sql,可为查询、删除、创建、更新等等的sql,在此可直接指定表名称,默认就是select * from tablename

con,指定的数据库连接,即con=engine,也就是我们刚才初始化的数据库连接engine

index_col,查询时,指定那一列为DataFrame的index,也可以是多列['a','b'],此时就生成了Multindex

coerce_float,boolean,默认为True,尝试转换float的值,用于设置sql查询的结果

params,list, tuple or dict, 可选关键字, 默认为:None,要传递给执行方法的参数列表。不太懂这个关键字,一般情况用不到

parse_dates, list or dict, 默认为 None,要解析为日期时间的字段

columns,查询时指定选择那些列,即select *  from 中的*,默认全部列

chunksize,int,默认为None,如果指定数值,则返回一个迭代器,指定的数值为迭代器内数据的行数

data=pd.read_sql('stock_basic',engine)

data.head()
Out[41]: 
     ts_code  symbol   name area industry market list_date
0  000702.SZ  000702   正虹科技   湖南       饲料     主板  19970318
1  000703.SZ  000703   恒逸石化   广西       化纤     主板  19970328
2  000705.SZ  000705   浙江震元   浙江     医药商业     主板  19970410
3  000707.SZ  000707  *ST双环   湖北     化工原料     主板  19970415
4  000708.SZ  000708   大冶特钢   湖北      特种钢     主板  19970326

data=pd.read_sql('stock_basic',engine,index_col='ts_code',columns=['symbol','industry'])

data.head()
Out[43]: 
           symbol industry
ts_code                   
000702.SZ  000702       饲料
000703.SZ  000703       化纤
000705.SZ  000705     医药商业
000707.SZ  000707     化工原料
000708.SZ  000708      特种钢

需注意:使用read_sql方式执行诸如drop /create/truncate等操作时,因没有返回结果数据会报错(但已执行成功),针对如此情况,若需要程序继续运行,可尝试加入try捕捉错误,继续运行程序。

to_sql

to_sql为DataFrame的方法,用于写入数据库数据,可等同于create/insert

官方介绍:DataFrame.to_sql(self, name, con, schema=None, if_exists='fail', index=True, index_label=None, chunksize=None, dtype=None)

关键参数说明:

name,数据库表名

con,指定的数据库连接,即con=engine,也就是我们刚才初始化的数据库连接engine

schema,指定样式,不明白有什么用处

if_exists,{'fail', 'replace', 'append'}, 默认为'fail',即指定当数据库表存在时的处理方式,默认为fail,挂起一个错误

        * fail: 挂起一个错误
        * replace: drop掉原来的表,重新创建
        * append: 在原来表基础上插入数据

index,boolean,默认为True,指定DataFrame的index是否一同写入数据库

index_label,在index关键字为True时,指定写入的index的字段名称,默认为None时,字段名称为index

chunksize,int,默认为None,如果指定数值,则返回一个迭代器,指定的数值为迭代器内数据的行数。当写入的数据量较大时,最好指定此关键字的数值

dtype,dict, 可选关键字,默认为None,即指定写入的字段字符类型,注意做好指定字符类型,因默认写入的数据类型数是colb,若没有指定数据类型,估计会报错。

to_sql用法实战

DataFrame.to_sql方法可直接将DataFrame数据写入的数据库中的表,表在数据库中可存在,可不存在,因不同类型的数据库其字符类型不相同,若不指定写入数据的字符类型,往往会出现我们意想不到的错误,故为避免错误,指定写入的数据类型是非常有必要的,特别是表不存在时,我们直接用to_sql方法,相当于创建了一个表。

写入数据的字符类型可通过dtype关键字来指定,为方便起见我们定义了一个函数,自动获取DataFrme各列的数据类型,生成字典。

#导入支持oracle的数据类型
from sqlalchemy.dialects.oracle import \
            BFILE, BLOB, CHAR, CLOB, DATE, \
            DOUBLE_PRECISION, FLOAT, INTERVAL, LONG, NCLOB, \
            NUMBER, NVARCHAR, NVARCHAR2, RAW, TIMESTAMP, VARCHAR, \
            VARCHAR2

#定义函数,自动输出DataFrme数据写入oracle的数类型字典表,配合to_sql方法使用(注意,其类型只能是SQLAlchemy type )
def mapping_df_types(df):
    dtypedict = {}
    for i, j in zip(df.columns, df.dtypes):
        if "object" in str(j):
            dtypedict.update({i: VARCHAR(256)})
        if "float" in str(j):
            dtypedict.update({i: NUMBER(19,8)})
        if "int" in str(j):
            dtypedict.update({i: VARCHAR(19)})
    return dtypedict

由此便创建了函数mapping_df_types,自动获取DataFrame各列的字符类型,用于dtype关键字

data_base.to_sql('stock_class',engine,index=False,if_exists='append',dtype=dtypedict,chunksize=100)

OK,到此我们便完成了数据的写入,同时也指定的了写入的数据类型,当‘stock_class’表存在时,在原来数据基础上插入数据,若不存在,则自动生成‘stock_class’表,表内每个字段的字符类型也同时指定了。

你可能感兴趣的:(Python,Pandas)