一、python实现oracle数据迁移到mysql源码
1.1
import cx_Oracle
import pymysql
import time
def migrate_sql():
source_db = cx_Oracle.connect('user', 'passoword', '133.*.*.*:*****/**') # 源库
target_db = pymysql.connect("10.*.*.*", "user", "passoword", "shujuku") # 目标库
# 2.创建游标
cur_select = source_db.cursor() # 源库查询对象
cur_insert = target_db.cursor() # 目标库插入对象
# 3.执行SQL
sql_select = "SELECT ACC_NUM,ADDRESS_DESC FROM ORD_SO.ORD_PROD_INST@to_crm30db where acc_num = 'g3228747'"
cur_select.execute(sql_select)
# 获取源表有多少个列
desc = cur_select.description
col_len = len(desc)
# MySQL批量插入语法是 insert into tb_name values(%s,%s,%s,%s)
val_str = ''
for i in range(1, col_len):
val_str = val_str + '%s' + ','
val_str += '%s'
# # Oracle批量插入语法是 insert into tb_name values(:1,:2,:3)
# for i in range(1, col_len):
# val_str = val_str + ':' + str(i) + ','
# val_str = val_str + ':' + str(col_len)
# 拼接insert into 目标表 values #目标表插入语句
insert_sql = 'insert into boss_ord_prod_inst' + ' values(' + val_str + ')'
cur_select.execute(sql_select) # 执行
print('开始执行:', time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
while True:
# 每次获取500行,由cur_select.arraysize值决定,MySQL fetchmany 返回的是 tuple 数据类型 所以用list做类型转换
rows = list(cur_select.fetchmany(100))
# 批量插入每次500行,需要注意的是 rows 必须是 list [] 数据类型
cur_insert.executemany(insert_sql, rows)
target_db.commit() # 提交
if not rows:
break # 中断循环
cur_select.close()
cur_insert.close()
source_db.close()
target_db.close()
print('执行成功:', time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
migrate_sql()
1.2
def sqlMigrate_boss():
source_db = cx_Oracle.connect('xy_other', '********', '133.0.**.**:**/xydb') # 源库
target_db = pymysql.connect('10.37.**.**', 'root', '********', 'enterprise_internet') # 目标库
# 2.创建游标
cur_select = source_db.cursor() # 源库查询对象
cur_insert = target_db.cursor() # 目标库插入对象
# 3.执行SQL
sql_select_prod_inst = "SELECT distinct prod_inst_id,acc_num,address_desc,prod_id," \
"owner_cust_id,owner_cust_name,region_id,create_date " \
"FROM ORD_SO.ORD_PROD_INST@to_crm30db where acc_num ='g3212018'"
sql_select_contact_info = "SELECT distinct prod_inst_id, owner_cust_id " \
"FROM ORD_SO.ORD_PROD_INST@to_crm30db where acc_num ='g3212018'"
cur_select.execute(sql_select_prod_inst)
# 获取源表有多少个列
desc = cur_select.description
col_len = len(desc)
# MySQL批量插入语法是 insert into tb_name values(%s,%s,%s,%s)
val_str = ''
for i in range(1, col_len):
val_str = val_str + '%s' + ','
val_str += '%s'
# 拼接insert into 目标表 values #目标表插入语句
sql_insert_prod_inst = 'insert into bossInfo_prod_inst(prod_inst_id,acc_num,address_desc,prod_id,' \
'owner_cust_id,owner_cust_name,region_id,create_date)' \
+ ' values(' + val_str + ')'
# 拼接insert into 目标表 values #目标表插入语句
sql_insert_contact_info = 'insert into bossInfo_contact_info(prod_inst_id, owner_cust_id) values(%s,%s)'
print('开始执行prod_inst:', time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
cur_select.execute(sql_select_prod_inst)
while True:
# 每次获取100行,由cur_select.arraysize值决定,MySQL fetchmany 返回的是 tuple 数据类型 所以用list做类型转换
rows = list(cur_select.fetchmany(10))
# 批量插入每次100行,需要注意的是 rows 必须是 list [] 数据类型
cur_insert.executemany(sql_insert_prod_inst, rows)
target_db.commit() # 提交
if not rows:
break # 中断循环
print('执行成功prod_inst:', time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
print('开始执行contact_info:', time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
cur_select.execute(sql_select_contact_info)
while True:
# 每次获取10行,由cur_select.arraysize值决定,MySQL fetchmany 返回的是 tuple 数据类型 所以用list做类型转换
rows = list(cur_select.fetchmany(10))
# 批量插入每次10行,需要注意的是 rows 必须是 list [] 数据类型
cur_insert.executemany(sql_insert_contact_info, rows)
target_db.commit() # 提交
if not rows:
break # 中断循环
print('执行成功contact_info:', time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
print('开始执行contact_info_update:', time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
cur_insert.execute('select prod_inst_id,owner_cust_id from bossInfo_contact_info where cust_manager is null')
data_contact = cur_insert.fetchall()
for prod, owner in data_contact:
# 更新mobile_phone
sql_select_cust_mobile = "select mobile_phone from CUS_CUST.CONTACTS_INFO@to_crm30db where contact_id = (" \
"select contact_id from CUS_CUST.CUST_CONTACT_INFO_REL@to_crm30db " \
" where cust_id =" + owner + ")"
cur_select.execute(sql_select_cust_mobile)
rows = list(cur_select.fetchone())
sql_update_contact_info = "UPDATE bossInfo_contact_info set cust_mobile_phone =" + rows[0] + \
" where owner_cust_id =" + owner
cur_insert.execute(sql_update_contact_info)
# 跟新manage_mobile_phone
sql_select_manage_mobile = "select attr_value from ord_so.ord_prod_inst_attr@to_crm30db " \
" where prod_inst_id =" + prod + "and attr_id = 4605"
cur_select.execute(sql_select_manage_mobile)
rows = list(cur_select.fetchone())
sql_update_contact_info = "UPDATE bossInfo_contact_info set manager_mobile_phone =" + rows[0] + \
" where owner_cust_id =" + owner
cur_insert.execute(sql_update_contact_info)
# 跟新cust_manage
sql_select_manager = "select attr_value from ord_so.ord_prod_inst_attr@to_crm30db " \
" where prod_inst_id =" + prod + "and attr_id = 4604"
cur_select.execute(sql_select_manager)
rows = list(cur_select.fetchone())
sql_update_contact_info = "UPDATE bossInfo_contact_info set cust_manager =" + "'" + rows[0]+"'" + \
" where owner_cust_id =" + owner
cur_insert.execute(sql_update_contact_info)
target_db.commit() # 提交
print('执行成功contact_info_update:', time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
cur_select.close()
cur_insert.close()
source_db.close()
target_db.close()
二、Navicat Premium工具迁移实现
在navicat里面连接MySQL和Oracle数据库
数据库连接完成后,打开工具——数据传输:
源:选择Oracle
目标:选择目标MySQL数据库
bug
问: execute executemany 游标执行 cur_insert.executemany(insert_sql_contact_info, rows) 报:pymysql.err.OperationalError: (1136, "Column count doesn't match value count at row 1")
答
insert_sql_contact_info = 'insert into bossInfo_contact_info
(prod_inst_id, owner_cust_id) values("%s,%s")'
改为:
insert_sql_contact_info = 'insert into bossInfo_contact_info
(prod_inst_id, owner_cust_id) values(%s,%s)'