背景
一直用Java技术栈,最近公司有项目用到了python的技术栈,在公司前人探索的基础上,用了cx_oracle作为持久层的工具,遇到了一个具体的问题是需要insert大约5万条数据到oracle数据库
问题描述
oracle数据库是没有主键自增的,在插入数据时,如何实现主键的自动生成以及插入速度的提升是需要实际解决的问题
解决方案
先上代码,这里省略了关于cx_oracle知识,如需了解请点击本链接。
# -*- coding:utf-8 -*-
# @Time: 3/12/2021 3:56 PM
# @Author: Gordon.Zhang
# @File: tests.py
import datetime
import os
import platform
import cx_Oracle
oracle_lib_dir = "D:\\software\python\\instantclient_19_9"
os_name = platform.platform();
if os_name.startswith('Windows'):
cx_Oracle.init_oracle_client(oracle_lib_dir)
sys_editor = 'system_job_editor'
data_source_user_name = os.getenv("DB_USER")
data_source_password = os.getenv("DB_PASSWORD")
data_source_url = os.getenv("DB_URL")
oracle_con = cx_Oracle.connect(data_source_user_name, data_source_password, data_source_url)
finish_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
cursor = oracle_con.cursor()
params=[]
for i in range(0, 20000, 1):
param = (258, "1235481544548548", 1, finish_time, sys_editor, finish_time, sys_editor)
params.append(param)
cursor.executemany("INSERT INTO T_ABS_RS_RESULT_SET_DETAIL VALUES (table_sqquence_value.NEXTVAL, :2, :3, :4, TO_TIMESTAMP(:5, 'YY-MM-DD HH24:MI:SS'), :6, ""TO_TIMESTAMP(:7, 'YY-MM-DD HH24:MI:SS'), :8)",
params)
oracle_con.commit()
cursor.close()
oracle_con.close()
在解决方案中,插入多条数据我们用的是executemany方法,下面是该方法所给的官方示例
dataToInsert = [
(10, 'Parent 10'),
(20, 'Parent 20'),
(30, 'Parent 30'),
(40, 'Parent 40'),
(50, 'Parent 50')
]
cursor.executemany("insert into ParentTable values (:1, :2)", dataToInsert)
executemany方法所给参数为两个,一个是sql语句,:1, :2表示占位符,一个参数是list类型的参数,list的len表示插入数据的条数。
在最开始要解决插入数据获得主键问题利用sequence,每次获取nextval,但是每次都要连接数据数据库读取值,然后构造放入list中,最后作为参数传递,这样效率较慢。在网上查找了很久,找到了相应的办法,在insert的sql语句中,关于id的value直接写入读取sequence的值,这样每次插入数据时,不需要构造主键相关的参数,大大提升效率。