‘’‘不使用excel文件直接导出数据,正式迁移以此版本为准’’’
‘’‘20240408 timestamp字段带毫秒,迁移时to_date报错,将此类型字段转为日月年时分称标准格式后处理’’’
from cmath import nan
from datetime import datetime
import openpyxl
import decimal
import re
import pandas as pd
import numpy as np
import matplotlib.pyplot as pyplot
from sqlalchemy import true
import cx_Oracle
#将字符串按指定长度截取后返回list,最后不够位数的同样返回
def fixSplitStr(splitStr,fix_len):
ls_str=[]
if len(splitStr) > fix_len:
left = 0
for i in range(len(splitStr)):
if i % fix_len == 0:
ls_str.append(splitStr[left: i])
left = i
#对剩余的判断,有可能会出现刚好处于分割整数倍的情况,所以必须要用<=分割长度,如果用<,可能会发生最后一段丢失的情况
elif (len(splitStr) - left <= fix_len):
# print(len(splitStr) - left)
ls_str.append(splitStr[left:len(splitStr)])
break
else:
ls_str.append(splitStr)
#清除第一个空元素,因为 0%n=0,会添加一个空元素
del(ls_str[0])
return(ls_str)
basePath=“C:\Users\MyComputer\Desktop\xxxxx\”
outputBasePath=r"C:\Users\MyComputer\Desktop\DB脚本\维权系统\sql"
db2_filename=basePath+“db2_output.sql”
mysql_filename=basePath+“mysql_output.sql”
oracle_filename=basePath+“oracle_output.sql”
sqlserver_filename=basePath+“sqlserver_output.sql”
db2_filename=outputBasePath+"\db2\全量\KMPF_02_InsertData.sql"
mysql_filename=outputBasePath+"\mysql\全量\KMPF_02_InsertData.sql"
oracle_filename=outputBasePath+"\oracle\全量\KMPF_02_InsertData.sql"
sqlserver_filename=outputBasePath+"\sqlserver\全量\KMPF_02_InsertData.sql"
postgresql_filename=outputBasePath+"\postgresql\全量\KMPF_02_InsertData.sql"
db2_file=open(db2_filename,mode=“w”,encoding=“utf-8”)
mysql_file=open(mysql_filename,mode=“w”,encoding=“utf-8”)
oracle_file=open(oracle_filename,mode=“w”,encoding=“utf-8”)
sqlserver_file=open(sqlserver_filename,mode=“w”,encoding=“utf-8”)
postgresql_file=open(postgresql_filename,mode=“w”,encoding=“utf-8”)
#数据库脚本初始化,屏蔽oracle &变量定义字符
oracle_file.writelines(“set define off;\n”)
#连接指定的数据库
connection = cx_Oracle.connect(user=“test”, password=“rootrootrootroot”,dsn=“10.10.122.84:1521/orcl”)
connection = cx_Oracle.connect(user=“dhcc01”, password=“dhcc010203”,dsn=“172.28.30.88:1521/orcl”)
#使用cursor()方法获取操作游标
cursor = connection.cursor()
#取出所有表名
cursor.execute(""“select table_name from user_tables “””)
tablenames=cursor.fetchall()
#取出表列的类型,写入到字典中去
table_column_datatype_dict={}
for tmp_tablename in tablenames:
# print(tmp_tablename[‘table_name’])
v_tablename=tmp_tablename[0]
param={‘tabname’:v_tablename}
cursor.execute(""“select table_name,column_name,data_type from user_tab_columns where table_name= :tabname order by column_id asc”"",param )
tablecolumns=cursor.fetchall()
tmp_table_columns=[]
tmp_table_indexes=[]
#检索每行
tmp_column_order=0
for column in tablecolumns:
tmp_column_order+=1
v_tablename=column[0]
v_columnname=column[1]
v_columntype=column[2]
v_key={tmp_column_order:(v_tablename,v_columnname,v_columntype)}
# print(v_key)
#键值对插入更新
table_column_datatype_dict.update(v_key)
insert_str='insert into '+v_tablename+'('
#检索列名,生成列语句,以逗号分隔
for column in tablecolumns:
insert_str=insert_str+column[1]+','
#删除多余的逗号
insert_len=len(insert_str)
insert_str=insert_str[0:insert_len-1]
insert_str+=') values('
#primaryKey,默认是首列
primaryKey=tablecolumns[0][1]
# print(primaryKey)
# exit(0)
#开始处理每一行
# cursor.execute("""alter session set nls_timestamp_format = 'yyyy-mm-dd hh24:mi:ss'""")
# cursor.execute("""alter session set nls_date_format = 'yyyy-mm-dd hh24:mi:ss'""")
cursor.execute("""select * from """+v_tablename )
#多少行提交一次
commit_counter=0
commit_count=1000
for row in cursor:
#四种库语句字符串
db2_insert_str=insert_str
oracle_insert_str=insert_str
mysql_insert_str=insert_str
sqlserver_insert_str=insert_str
postgresql_insert_str=insert_str
#针对每一行将超长的列写入超长字典中去
split_column_dict={}
#通过列顺序来取出表名列名列类型
tmp_column_order=0
for column in row:
tmp_column_order+=1
size_exceed_mark=False
size_exceed_column_split=None
v_tablename=table_column_datatype_dict[tmp_column_order][0]
v_columnname=table_column_datatype_dict[tmp_column_order][1]
v_columntype=table_column_datatype_dict[tmp_column_order][2]
#首先判断此列是否超长,如果超长,oracle是clob字段
value_column=str(column)
len_column=len(value_column)
# print(len_column)
# print(str(column))
# 后面还需要转义字符,添加后可能大于4000,小一点
if len_column>2000:
size_exceed_mark=True
#不能直接按4000分割,因为要加q'~分隔符,这样同样会超过4000
size_exceed_column_split=fixSplitStr(value_column,1000)
# print(size_exceed_column_split)
# for s in size_exceed_column_split:
# print('***********************')
# print(s)
#每列存一个字典值,每行首列ID值是不变的,可以直接取
split_column_dict.setdefault(v_columnname,size_exceed_column_split)
# print(v_columntype)
if v_columntype=="DATE":
if not pd.isnull(column):
# 迁移时只要日月年时分秒数据
column=datetime.strftime(column,'%Y-%m-%d %H:%M:%S')
db2_valuestring="timestamp('"+str(column)+"')"
oracle_valuestring="to_date('"+str(column)+"','yyyy/mm/dd hh24:mi:ss')"
mysql_valuestring="'"+str(column)+"'"
sqlserver_valuestring="N'"+str(column)+"'"
postgresql_valuestring="'"+str(column)+"'"
elif v_columntype=="TIMESTAMP":
if not pd.isnull(column):
# 迁移时只要日月年时分秒数据
column=datetime.strftime(column,'%Y-%m-%d %H:%M:%S')
db2_valuestring="timestamp('"+str(column)+"')"
oracle_valuestring="to_date('"+str(column)+"','yyyy/mm/dd hh24:mi:ss')"
mysql_valuestring="'"+str(column)+"'"
sqlserver_valuestring="N'"+str(column)+"'"
postgresql_valuestring="'"+str(column)+"'"
elif v_columntype=="TIMESTAMP(6)":
if not pd.isnull(column):
# 迁移时只要日月年时分秒数据
column=datetime.strftime(column,'%Y-%m-%d %H:%M:%S')
db2_valuestring="timestamp('"+str(column)+"')"
oracle_valuestring="to_date('"+str(column)+"','yyyy/mm/dd hh24:mi:ss')"
mysql_valuestring="'"+str(column)+"'"
sqlserver_valuestring="N'"+str(column)+"'"
postgresql_valuestring="'"+str(column)+"'"
elif v_columntype=="INT":
db2_valuestring=str(column)
mysql_valuestring=str(column)
oracle_valuestring=str(column)
sqlserver_valuestring="N'"+str(column)+"'"
postgresql_valuestring=str(column)
elif v_columntype=="NUMBER":
db2_valuestring=str(column)
mysql_valuestring=str(column)
oracle_valuestring=str(column)
sqlserver_valuestring="N'"+str(column)+"'"
postgresql_valuestring=str(column)
elif v_columntype=="INTEGER":
db2_valuestring=str(column)
mysql_valuestring=str(column)
oracle_valuestring=str(column)
sqlserver_valuestring="N'"+str(column)+"'"
postgresql_valuestring=str(column)
elif v_columntype=="LONG":
db2_valuestring=str(column)
mysql_valuestring=str(column)
oracle_valuestring=str(column)
sqlserver_valuestring="N'"+str(column)+"'"
postgresql_valuestring=str(column)
elif v_columntype=="FLOAT":
db2_valuestring=str(column)
mysql_valuestring=str(column)
oracle_valuestring=str(column)
sqlserver_valuestring="N'"+str(column)+"'"
postgresql_valuestring=str(column)
elif v_columntype=="DECIMAL":
db2_valuestring=str(column)
mysql_valuestring=str(column)
oracle_valuestring=str(column)
sqlserver_valuestring="N'"+str(column)+"'"
postgresql_valuestring=str(column)
elif v_columntype=="RAW":
db2_valuestring=str(column)
mysql_valuestring=str(column)
oracle_valuestring=str(column)
sqlserver_valuestring=str(column)
postgresql_valuestring=str(column)
elif v_columntype=="BLOB":
db2_valuestring=str(column)
mysql_valuestring=str(column)
oracle_valuestring=str(column)
sqlserver_valuestring=str(column)
postgresql_valuestring=str(column)
elif v_columntype=="CHAR":
db2_valuestring="'"+str(column)+"'"
mysql_valuestring="'"+str(column)+"'"
oracle_valuestring="'"+str(column)+"'"
sqlserver_valuestring="N'"+str(column).replace("'","''")+"'"
postgresql_valuestring="'"+str(column)+"'"
elif v_columntype=="VARCHAR":
db2_valuestring="'"+str(column)+"'"
mysql_valuestring="'"+str(column)+"'"
oracle_valuestring="'"+str(column)+"'"
sqlserver_valuestring="N'"+str(column).replace("'","''")+"'"
postgresql_valuestring="'"+str(column)+"'"
elif v_columntype=="VARCHAR2":
db2_valuestring="'"+str(column)+"'"
mysql_valuestring="'"+str(column)+"'"
oracle_valuestring="'"+str(column)+"'"
sqlserver_valuestring="N'"+str(column).replace("'","''")+"'"
postgresql_valuestring="'"+str(column)+"'"
elif v_columntype=="CLOB":
#对应db2的long varchar,同oracle一样,有超长限制,同时需要转义字符
if size_exceed_mark==False:
db2_valuestring="'"+str(column).replace("\\","\\\\").replace('"','\\"').replace("'","\\''")+"'"
else:
db2_valuestring='NULL'
#需要转义单引号
mysql_valuestring="'"+str(column).replace("\\","\\\\").replace('"','\\"').replace("'","\\'")+"'"
#需要转义单引号
sqlserver_valuestring="N'"+str(column).replace("'","''")+"'"
#只有mysql的text列,才需要判断
if size_exceed_mark==False:
oracle_valuestring="q'~"+str(column)+"~'"
else:
oracle_valuestring='NULL'
#需要转义单引号
postgresql_valuestring="'"+str(column).replace("'","''")+"'"
else:
db2_valuestring=str(column)
mysql_valuestring=str(column)
oracle_valuestring=str(column)
sqlserver_valuestring="N'"+str(column)+"'"
postgresql_valuestring=str(column)
#pandas中,nan指的是null,要用专门方法判断
if pd.isnull(column):
db2_valuestring='NULL'
mysql_valuestring='NULL'
oracle_valuestring='NULL'
sqlserver_valuestring='NULL'
postgresql_valuestring='NULL'
# print(db2_valuestring)
# print(mysql_valuestring)
# print(oracle_valuestring)
# print(sqlserver_valuestring)
#循环中构建values,以逗号分隔
db2_insert_str+=db2_valuestring+","
oracle_insert_str+=oracle_valuestring+","
mysql_insert_str+=mysql_valuestring+","
sqlserver_insert_str+=sqlserver_valuestring+","
postgresql_insert_str+=postgresql_valuestring+","
#去除最后一个多添加的逗号
db2_insert_len=len(db2_insert_str)
db2_insert_str=db2_insert_str[0:db2_insert_len-1]
db2_insert_str+=");\n"
oracle_insert_len=len(oracle_insert_str)
oracle_insert_str=oracle_insert_str[0:oracle_insert_len-1]
oracle_insert_str+=");\n"
mysql_insert_len=len(mysql_insert_str)
mysql_insert_str=mysql_insert_str[0:mysql_insert_len-1]
mysql_insert_str+=");\n"
sqlserver_insert_len=len(sqlserver_insert_str)
sqlserver_insert_str=sqlserver_insert_str[0:sqlserver_insert_len-1]
sqlserver_insert_str+=");\n"
postgresql_insert_len=len(postgresql_insert_str)
postgresql_insert_str=postgresql_insert_str[0:postgresql_insert_len-1]
postgresql_insert_str+=");\n"
# print(db2_insert_str)
# print(oracle_insert_str)
# print(mysql_insert_str)
# print(sqlserver_insert_str)
db2_file.writelines(db2_insert_str)
oracle_file.writelines(oracle_insert_str)
mysql_file.writelines(mysql_insert_str)
sqlserver_file.writelines(sqlserver_insert_str)
postgresql_file.writelines(postgresql_insert_str)
# 在每个insert行的末尾,要看此行里是否有超长的clob列,动态生成update语句
# 处理完成后,split_column_dict会在下一次使用前销毁
# print(len(split_column_dict))
if len(split_column_dict)>0:
# v_tablename= tmp_tablename
#默认首列是主键列更新,一般是ID,但是由于有大小写问题,直接用首列序号
v_tableid = str(row[0])
#遍例字典
for tmp_dict in split_column_dict:
# print(tmp_dict)
v_columnname=tmp_dict
# print('***********************************')
#key值对应的是个list
for tmp_split_row in split_column_dict[tmp_dict]:
# print('######################################')
# print(tmp_split_row)
v_oracle_update_str='update '+v_tablename+' set '+v_columnname+'='+v_columnname+'||'+"q'~"+tmp_split_row+"~'"+"\n where "+primaryKey+"='"+v_tableid+"';"
oracle_file.writelines(v_oracle_update_str+"\n")
v_db2_update_str='update '+v_tablename+' set '+v_columnname+'='+v_columnname+'||'+"'"+tmp_split_row.replace("\\","\\\\").replace('"','\\"').replace("'","\\''")+"'"+"\n where "+primaryKey+"='"+v_tableid+"';"
db2_file.writelines(v_db2_update_str+"\n")
#行循环中每行加1,指定commit_count添加commit命令
commit_counter+=1
if commit_counter%commit_count==0:
db2_file.writelines("commit;\n")
mysql_file.writelines("commit;\n")
oracle_file.writelines("commit;\n")
postgresql_file.writelines("commit;\n")
#单行测试时用
# break;
#每张表至少提交一次
db2_file.writelines("commit;\n")
mysql_file.writelines("commit;\n")
oracle_file.writelines("commit;\n")
postgresql_file.writelines("commit;\n")
#处理结束关闭文件
db2_file.close()
mysql_file.close()
oracle_file.close()
sqlserver_file.close()
postgresql_file.close()




