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’表,表内每个字段的字符类型也同时指定了。

### 如何将MariaDB的数据或应用迁移到Oracle数据库 #### 背景概述 MariaDB 和 Oracle 是两种不同的关系型数据库管理系统 (RDBMS),它们之间存在显著的技术差异。因此,从 MariaDB 到 Oracle 的迁移通常涉及逻辑导出和重新导入的过程。 为了成功完成这一过程,可以采用多种方法和技术工具来简化操作并减少潜在错误的发生率。以下是具体的方案、工具以及最佳实践: --- #### 方法一:使用通用SQL脚本进行数据转换 一种常见的做法是从 MariaDB 中提取数据到中间存储介质(如 CSV 文件),再将其加载到 Oracle 数据库中。此过程中可能需要编写自定义 SQL 脚本来处理字段映射和其他兼容性问题。 - **步骤说明** - 导出表结构与数据为纯文本形式。 - 修改 DDL (Data Definition Language)语句使其符合目标系统的语法要求[^1]。 - 使用 `INSERT INTO ... SELECT` 或批量插入命令填充新创建的目标表格。 ```sql -- 示例:假设有一个名为 'employees' 表格需转移 CREATE TABLE employees ( id INT PRIMARY KEY, name VARCHAR(50), hire_date DATE ); -- 将原始记录复制过来 INSERT INTO target_employees(id,name,hire_date) SELECT * FROM source_employees; ``` --- #### 方法二:利用第三方ETL工具加速进程 企业级环境中推荐运用专业的 ETL (Extract Transform Load) 解决方案比如 Talend Open Studio , Informatica PowerCenter 等产品来进行跨平台间的大规模数据搬运工作。这些商业软件往往内置丰富的连接器支持主流 RDBMS 平台间的无缝对接,并提供图形化界面降低技术门槛。 另一种选择则是官方推出的 Oracle SQL Developer ,它同样具备一定的异构迁移能力,尽管主要针对的是 MySQL/MariaDB 至 Oracle 场景下的简单场景[^4]。 --- #### 方法三:基于程序代码实现自动化流程控制 对于高度定制化的业务需求或者频繁发生的同类任务,则考虑开发专属的应用层服务更为合适。Python 结合 pandas 库能够轻松读写 Excel/CSV 类型文档;而 SQLAlchemy ORM 层面则允许构建抽象模型描述不同类型的持久化对象之间的关联关系。 下面给出一段简单的 Python 实现片段用于演示目的: ```python import sqlalchemy as sa from sqlalchemy.orm import sessionmaker def migrate_data(source_engine_url, dest_engine_url): # 创建引擎实例 src_engine = sa.create_engine(source_engine_url) dst_engine = sa.create_engine(dest_engine_url) Session = sessionmaker(bind=dst_engine) db_session = Session() metadata = sa.MetaData() try: with src_engine.connect() as conn: result_set = conn.execute("SELECT * FROM some_table;") table_def = sa.Table('some_other_table', metadata, autoload_with=dst_engine) ins_stmt = table_def.insert().values([dict(row) for row in result_set]) db_session.execute(ins_stmt) db_session.commit() finally: db_session.close() if __name__ == "__main__": mariadb_conn_str = "mysql+pymysql://user:password@localhost/mariadb_db" oracle_conn_str = "oracle+cx_oracle://scott:tiger@tns_name" migrate_data(mariadb_conn_str, oracle_conn_str) ``` 上述例子展示了如何借助 SQLAlchemy 来桥接两个完全不一样的后端存储系统,同时保持较高的灵活性以便适应未来可能出现的变化[^3]. --- #### 最佳实践建议 无论采取哪种具体手段执行实际迁移动作之前都应该做好充分准备功课: - 彻底审查源目两端环境配置参数一致性; - 测试验证所有必要的功能模块正常运作无误之后才正式上线切换; - 记录整个项目周期内的关键决策点及其理由依据便于后续审计追踪. 此外还要注意保护敏感信息安全不泄露给未经授权的人士访问接触[^2]. ---
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值