Python数据库迁移脚本(终极版)
上次的那几个脚本这次全部整合到了一起,而且后面发现了一个可以使用的ODBC包,于是这次采用的方式就很简单了,直接通过ODBC将InterBase数据库中的数据全部取出来之后通过Python的sqlalchemyORM框架直接连接远程的MySQL数据库,之后便可以方便的传递数据了,当然,作为我的终极完善版本,自动模式和手动模式是少不了的了,在自动模式中将自动检查InterBase数据库是否存在,如果不存在则自动restore,然后自己创建InterBase的数据源,之后便可以取出数据了,下面是流程图。

那么下面就是讲解代码的时候咯~
这次的这个脚步主要分为三个函数,main函数,odbc函数和restore函数,由于手动模式包含在自动模式中,那么我就只介绍自动模式了。
我在脚本中定义了一个字典用来存储脚本的配置信息,用户可以在字典中定义自己需要的功能和数据库信息等。
#定义一个配置字典,将所需的参数添加在字典中方便改动
setting = {
#设置启动模式
'operate_type':OPERATE_AUTO_RESTORE,
#备份文件的地址
'gbk_path':'C:\\XXX\\DB.gbk',
#需要恢复的InterBase数据库地址
'gdb_path':'C:\\\XXX\\\DB.GDB',
#设置需要连接的MySQL数据库的用户名,密码,ip地址和端口号
'username':'root', 'password':'root', 'port':'', 'dbname':'test', 'localhost':'127.0.0.1',
#设置需要连接的ODBC的名字以及用户名和密码
'DSN':'XXX','UID':'SYSDBA','PWD':'masterkey'}
在脚本启动的时候就通过判断来确定用户是以何种模式进行的脚本,紧接着运行适合的脚本
if __name__ == '__main__':
#判断启动模式是自动模式还是手动模式
if setting['operate_type']==OPERATE_AUTO_RESTORE:
#检查数据库是否存在,如果存在将跳过restore
if os.path.isfile('C:\\XXX\\DB.GDB') == False:
restore()
odbc()
main()
else:
print 'The database has been exist, will skip restore...'
odbc()
main()
elif setting['operate_type']==OPERATE_AUTO_EXPORT:
main()
当Python判断InterBase数据库不存在之后便执行restore来恢复数据库
#自动模式中恢复数据库的方法 def restore():
os.system('gbak -c -user "sysdba" -password "masterkey" "'+setting['gbk_path']+'" "127.0.0.1:'+setting['gdb_path']+'"')
之后便是自动创建InterBase的ODBC数据源了,当然首先要安装InterBase的驱动了,网上有很多,我就不一一的列出了,由于是在windows平台上运行的,所以很方便的就可以使用添加注册表的形式将需要的数据源添加进系统中了,当然,既然是通过注册表导入的那么就必然会产生出一个注册表文件了,我将它默认的生成在C盘的根目录,然后在导入完成之后再删除掉,这样就在脚本运行完之后也不会产生垃圾了。
#下面这个字符串创建了所需要的ODBC数据源,并将数据源中的数据库地址改为restore输出的数据库地址 def odbc():
odbcreg = '''Windows Registry Editor Version 5.00 [HKEY_CURRENT_USER\Software\ODBC\ODBC.INI] [HKEY_CURRENT_USER\Software\ODBC\ODBC.INI\kmk]
"Driver"="C:\\\WINDOWS\\\system32\\\OdbcFb32.dll"
"Description"=""
"Dbname"="'''+setting['gdb_path']+'''"
"Client"=""
"User"="SYSDBA"
"Role"=""
"CharacterSet"="NONE"
"JdbcDriver"="IscDbc"
"ReadOnly"="N"
"NoWait"="N"
"LockTimeoutWaitTransactions"=""
"Dialect"="3"
"QuotedIdentifier"="Y"
"SensitiveIdentifier"="N"
"AutoQuotedIdentifier"="N"
"UseSchemaIdentifier"="0"
"SafeThread"="Y"
"Password"="DKEBFJENHFCOBHGHLAIMNAAFICELEAEGDNMFNOGALAMHBBGCHFADNKCBPPGMANOGIEKENIOPHDIPBIECPLLLCBIKEJKMJLPLIB" [HKEY_CURRENT_USER\Software\ODBC\ODBC.INI\ODBC Data Sources]
"kmk"="Firebird/InterBase(r) driver" '''
#在C盘根目录下新建一个临时的注册表文件用来将新建的数据源导入 fp = open('C:\\db007.reg','w')
try:
fp.write(odbcreg)
except Exception,e:
print e
finally:
fp.close() #执行生成的数据源注册表文件 os.system('regedit /s C:\\db007.reg') #将临时产生的注册表文件删除 os.remove('C:\\db007.reg')
紧接着就是我们最关键的main函数咯~
当然了,这次和上次一样使用的是Python中SQLAlchemyORM的框架了,所以第一件事便是连接数据库,获得Session了,不过再次之前还是要先构建类与表的映射关系了。
#创建一个基类 Base = declarative_base() #定义一个User类与数据库进行映射 class User(Base):
__tablename__ = 'User'
NAME= Column(Integer, primary_key=True)
PASSWORD= Column(Integer)
.......
然后在获得Session之后便可以连接ODBC了,通过SQL语句将InterBase数据库中的数据取出来。
#创建数据库的连接
mysql_db = create_engine(
'mysql://'+setting['username']+':'+setting['password']+'@'+setting['localhost']+\
':'+setting['port']+'/'+setting['dbname'],echo=False)
Base.metadata.bind=mysql_db
Base.metadata.create_all(mysql_db)
#创建一个Session
Session = sessionmaker(bind=mysql_db)
session = Session()
#pdb.set_trace()
#创建与ODBC数据源的连接
conn = pyodbc.connect('DSN='+setting['DSN']+';UID='+setting['UID']+';PWD='+setting['PWD']+'')
curs = conn.cursor()
#通过SQL语句得到一个对象
dbf = curs.execute('select *from User')
下面就是自动模式与手动模式都必须进过的步骤了~通过循环将数据提交到MySQL中,当然,为了防止数据库中已经有了数据,那么就在添加之前检查数据库中是否有这个数据,如果有的话便跳过这次添加,继续后面的步骤。然后在每1000次添加之后提交一次数据,以减轻数据的压力,最后在循环外将除以1000的余数统一再存入数据库中。
#循环的将对象中的数据保存到User类中
commint = 0
for line1 in dbf:
#检查数据库中的数据是否有数据,如果没有则加入数据
exist = session.query(User).filter(User.ID == line1.ID,User.NAME == line1.NAME).count()
if exist>0:
continue
u = User()
u.NAME = line1.NAME
......
u.PASSWORD = line1.PASSWORD
session.add(u)
commint = commint+1
#当循环了1000次之后进行一次提交
if commint%1000==0:
try:
session.commit()
#pdb.set_trace()
session.flush()
except:
print 'error'
session.rollback()
#将剩余的数据进行提交
try:
session.commit()
session.flush()
except Exception , e:
print e
session.rollback()
session.close()
至此,这个是用ODBC读取数据然后在保存在MySQL的Python脚本就写完了,断断续续进过了一周多的日子,我实习的第一个正式任务也算是完美收官了,曾经在校园里学了几年的J2EE,万万没想到最后却来做了Python和数据库。。。。不知道后面的日子里还有什么样奇怪的任务等着我~~当然!我依旧不会放弃web的!加班狗努力!
Python数据库迁移脚本(终极版)的更多相关文章
- Python数据库备份脚本
Python数据库备份脚本 #!/usr/bin/env python # author: liudong # -*- coding: utf-8 -*- # filename: db_bak.py ...
- Python 数据库备份脚本
#!/usr/bin/python########################################################### Created date: 2017/12/7 ...
- Python 实现数据库更新脚本的生成
我在工作的时候,在测试环境下使用的数据库跟生产环境的数据库不一致,当我们的测试环境下的数据库完成测试准备更新到生产环境上的数据库时候,需要准备更新脚本,真是一不小心没记下来就会忘了改了哪里,哪里添加了 ...
- django迁移脚本
执行migrate报错的解决办法: 想知道migrate为什么报错,需要先了解migrate到底做了什么事情 migrate做了什么事情? 1.将相关的迁移脚本翻译成sql语句,然后在数据库中执行 2 ...
- 如何使用FluentMigrator进行数据库迁移
标题:如何使用FluentMigrator进行数据库迁移 地址:https://www.cnblogs.com/lwqlun/p/10649949.html 作者: Lamond Lu FluentM ...
- 数据库迁移框架Flyway介绍
官方文档 https://flywaydb.org/getstarted/firststeps/api[https://flywaydb.org/getstarted/firststeps/api] ...
- Saiku数据库迁移后的刷新脚本-Shell脚本读取数据库中的数据(二十三)
Saiku数据库迁移后的刷新脚本 之前有谈过对saiku中的数据进行刷新,因为saiku默认会从缓存中查询数据,但是配置不使用缓存又会效率低下... 所以这里就需要做一个数据刷新,每次ETL之后都需要 ...
- flask 使用Flask-Migrate迁移数据库(创建迁移环境、生成迁移脚本、更新数据库)
使用Flask-Migrate迁移数据库 在开发时,以删除表再重建的方式更新数据库简单直接,但明显的缺陷是会丢掉数据库中的所有数据.在生产环境下,没有人想把数据都删除掉,这时需要使用数据库迁移工具来完 ...
- [译]SQL数据库迁移:从低版到高版本
我见过太多的数据库管理员花大量的时间在数据库迁移上,即便在客户的实际环境亦是如此.由于微软频繁的发布新版,基于业务和客户的要求,应用服务不得不同时升级.当然,还有许多用户仍在使用SQL Server ...
随机推荐
- 【转】ASP.NET MVC学习笔记-Controller的ActionResult
1. 返回ViewResult public ActionResult Index() { ViewData["Message"] = "Welcome ...
- angularjs 中state.go 跳转并且打开新的浏览器窗口
包子最近遇到业务人员提的非常无厘头的需求,就是调页面的时候,一定要打开一个新的浏览器窗口...>o<奇葩!!! 但是我的页面都是state.go跳转的呀,我各种百度,发现,貌似state, ...
- jQuery入门(2)使用jQuery操作元素的属性与样式
jQuery入门(1)jQuery中万能的选择器 jQuery入门(2)使用jQuery操作元素的属性与样式 jQuery入门(3)事件与事件对象 jQuery入门(4)jQuery中的Ajax()应 ...
- 【总结】虚拟机VirtualBox各种使用技巧
作为个人学习研究,VirtualBox是首选,它是Oracle下免费的.开源.跨平台的一款虚拟机软件,小巧.实用,一点也不逊于商业版的VMware Workstation. VirtualBox官网: ...
- CentOS6.3 编译安装LAMP(2):编译安装 Apache2.2.25
所需源码包: /usr/local/src/Apache-2.2.25/httpd-2.2.25.tar.gz 编译安装 Apache2.2.25 #切换到源码目录 cd /usr/local/src ...
- class Solution(object): def fizzBuzz(self, n): a = [] i = 1 while(i <= n): if(i%15 == 0): a.append("FizzBuzz") elifleetcode day_01
412. Fizz Buzz Write a program that outputs the string representation of numbers from 1 to n. But fo ...
- c#微信开发 转
using System; using System.Collections.Generic; using System.Web; using System.Web.UI; using System. ...
- java基础 作业(一)
题目: 跳水比赛,8个评委打分.运动员的成绩是8个成绩去掉一个最高分,去掉一个最低分,剩下的6个分数 的平均分就是最后 得分.使用以为数组实现打分功能 .请把打分最高的评委和最低的评委找出来. 解析: ...
- poj 1192
此题亦一眼看出算法,一次AC. 没什么好讲的,就是一个普通的树形动规. 用dp[n][0]表示n号顶点不取时的最大值,dp[n][1]表示n号顶点取时的最大值. dp[n][0]=max{dp[x][ ...
- C# 委托及各种写法
委托是神马? 委托是一个类型安全的对象,它指向程序中另一个以后会被调用的方法(或多个方法).通俗的说,委托是一个可以引用方法的对象,当创建一个委托,也就创建一个引用方法的对象,进而就可以调用那个方法, ...