DB2
表复制方法介绍
Version:v1.0.0
Author
:
xiedd
Mail:xiedd@icss.com.cn
CreateDate:2006-08-29
LastEditDate:2006-08-30
说明
本文描述如何将DB2数据库中的一些表复制到另一个数据库中,适用于表中的数据量比较大(如1万条记录以上)的情况。当表中的数据量较少,并且表的数量不多时,可直接使用db2控制中心的表复制功能实现。
适用条件
n
DB2
中表的跨库复制,两个数据库可以在一台机器上,也可以在不同的机器上。(以下假设两个数据库位于不同的机器上。)
n
单一表中的数据量较大,通常在1万条记录数以上;
n
表的个数比较多;
术语定义
n
源数据库:需要复制的表存在的数据库;
n
目标数据库:需要复制的表复制后存在的数据库;
n
DDL:
数据定义语言,
用于建立和删除数据库以及数据库实体的命令。
总体说明
表的复制一般情况下用到了db2的以下几个命令:
1.
EXPORT:
导出表中的数据到数据文件中。
2.
IMPORT:
导入数据文件中的数据到表中。
3.
LOAD
:同IMPORT。区别是IMPORT需要写日志,而LOAD不需要,因此可以极大的提高数据的装载速度。
本文数据复制的思想是:首先通过DDL语言将源数据库中的表结构复制到目标数据库上,再通过批处理命令将源数据库中需要复制的表export成数据文件(IXF集成交换格式),然后将数据文件复制到目标数据库所在的机器上,通过load命令将数据文件装载到目标数据库中。
此过程主要使用了load命令以及避免了网络传输,可以极大提高数据的复制速度。而脚本的方式也提供了更好的扩展性,可对任意个数的表进行复制。同时针对某些复杂情况可使用程序支持对这些脚本的自动生成。
具体步骤
以下步骤假设:
l
源数据库为yndc
l
目标数据库为htdc
一、
创建生成DLL文件的批处理文件
本步骤创建文件dll.bat。
其内容语法示例如下:
db2look -d <dbname> -t <table1> <table2> <tableN> -e -nofed -o dll.sql
将<dbname>替换成源数据库的名称,<tableN>替换成具体的表名,多个表之间用空格分隔。如以下示例导出yndc数据库中的2个表DIM_GROUP和DIM_PJ_MACH的库表结构。
db2look -d yndc -t DIM_GROUP DIM_PJ_MACH -e -nofed -o dll.sql
二、
执行DLL批处理文件,生成DLL文件
本步骤执行dll.bat
将dll.bat复制到源数据库所在的机器上,在db2cmd环境中执行dll.bat,生成dll.sql。
三、
执行DLL文件
本步骤执行dll.sql
执行之前,更改dll.sql中目标数据库名称,并输入用户名和密码。同时必要情况下,更改表所在的表空间。
--
此 CLP 文件是使用 DB2LOOK 版本创建的 8.2
--
时间戳记: 2006-7-10 11:28:02
--
数据库名称: YNDC
--
数据库管理器版本: DB2/NT Version 8.2.4
--
数据库代码页: 1386
--
数据库整理顺序为: UNIQUE
CONNECT TO HTDC user db2admin using db2password;
------------------------------------------------
--
表的 DDL 语句 "DB2ADMIN"."BC_FACCIGTEMPLATE"
------------------------------------------------
CREATE TABLE "DB2ADMIN"."BC_FACCIGTEMPLATE" (
"CITYID" VARCHAR(30) NOT NULL ,
"CIGID" VARCHAR(30) NOT NULL ,
"CIGNAME" VARCHAR(50) NOT NULL ,
"ISUPLOAD" SMALLINT )
IN "HTDC"
;
--
表上的索引的 DDL 语句 "DB2ADMIN"."BC_FACCIGTEMPLATE"
CREATE INDEX "DB2ADMIN"."PK__BC_FACCIGTEMP1" ON "DB2ADMIN"."BC_FACCIGTEMPLATE"
("CITYID" ASC,
"CIGID" ASC) CLUSTER ;
--
表上主键的 DDL 语句 "DB2ADMIN"."BC_FACCIGTEMPLATE"
ALTER TABLE "DB2ADMIN"."BC_FACCIGTEMPLATE"
ADD CONSTRAINT "SQL051107160756210" PRIMARY KEY
("CITYID",
"CIGID");
COMMIT WORK;
CONNECT RESET;
TERMINATE;
然后进入db2cmd环境,切换到dll.sql所在的目录,执行以下命令:
注意查看执行结果是否正确。
四、
创建导出数据的EXPORT脚本
本步骤创建脚本export.bat
内容格式示例如下:
db2 connect to <dbname> user <username> using <password>
db2 "export to aa1.ixf of ixf select * from <table1>"
db2 "export to aa2.ixf of ixf select * from <table2>"
db2 "export to aa3.ixf of ixf select * from <table3>"
…
db2 connect reset
替换数据库名称、用户名、密码、表名。注意事项:多个表之间的集成交换格式文件按需要递增,如aa1.ixf,aa2.ixf,aa3.ixf...,并且要和后续的load脚本对应。
以下样例导出2个表的数据,样例如下:
db2 connect to yndc user db2admin using db2password
db2 "export to aa1.ixf of ixf select * from DIM_GROUP"
db2 "export to aa2.ixf of ixf select * from DIM_PJ_MACH"
db2 connect reset
五、
执行export脚本
本步骤执行export.bat
在源数据库所在的机器上,在db2cmd环境中执行export.bat。N个表将生成N个集成交换格式数据文件(后缀名.ixf)。
六、
将导出的数据压缩复制到目标数据库所在机器,并解压缩
将数据文件打成rar或zip包,复制到目标机器上,并解压缩。
七、
构建导入数据的LOAD脚本
本步骤在数据文件(IXF)所在的目录中创建load.bat。
内容格式示例如下:
db2 connect to <dbname> user <username> using <password>
db2 "load from aa1.ixf of ixf replace into <table1> COPY NO without prompting " > 1_<table1>.log
db2 "load from aa2.ixf of ixf replace into <table2> COPY NO without prompting " > 2_<table2>.log
…
db2 connect reset
替换数据库名称、用户名、密码、表名。注意事项:集成交换格式文件(ixf)对应的表名要和export时导出的表名对应。
以下样例导入2个表的数据,样例如下:
db2 connect to yndc user db2admin using db2password
db2 "load from aa1.ixf of ixf replace into DIM_GROUP COPY NO without prompting " > 1_DIM_GROUP.log
db2 "load from aa2.ixf of ixf replace into DIM_PJ_MACH COPY NO without prompting " > 2_DIM_PJ_MACH.log
db2 connect reset
八、
执行load脚本,检查执行结果
本步骤执行export.bat
在db2cmd环境中切换到load.bat所在的目录,执行load.bat。
执行完成之后N个表将生成N个log文件,逐一检查这些log文件,以确定数据load是否正常。
所有步骤结束!
附录1:重命名表的名称
如果需要将表复制到目标数据库时使用不同的名称,可在以上步骤完成之后,再编辑一个脚本,执行表的重命名操作。示例如下:
db2 connect to <dbname> user <username> using <password>
db2 rename <table1_old> to <table2_new>
db2 rename <table2_old> to <table3_new>
...
db2 connect reset
附录2:使用程序生成脚本
当表的数量较多,手工编辑脚本比较复杂时,可通过java程序生成dll.bat,export.bat和load.bat。
示例如下:
/**
* <p>Title:
数据库集成服务类,支持对yndc等数据库进行集成</p>
* @version 1.0
*/
public class DBEAIService {
/**
*
数据文件存放目录
*/
private String DEST_DIR = Globals.ManagerHome + "/output";
/**
*
日志记录器
*/
private static Logger log = Logger.getLogger(DBEAIService.class);
public DBEAIService() {
}
/**
*
创建导出脚本
* @param conn
* @param creator
表创建者
* @param filePath
*/
private void createExportFile(Connection conn, String creator,
String filePath) throws Exception {
DBBase dbBase = new DBBase(conn);
String selectTableSql =
"select name from sysibm.systables where creator = '"
+ creator + "' and type='T' order by name";
try {
dbBase.executeQuery(selectTableSql);
} catch (Exception ex) {
throw ex;
} finally {
dbBase.close();
}
DBResult result = dbBase.getSelectDBResult();
List list = new ArrayList();
while (result.next()) {
String table = result.getString(1);
list.add(table);
}
StringBuffer sb = new StringBuffer();
String enterFlag = "\r\n";
for (int i = 0; i < list.size(); i++) {
String tableName = (String) list.get(i);
sb.append("db2 \"export to aa" + String.valueOf(i + 1)
+ ".ixf of ixf select * from " + tableName + "\"");
sb.append(enterFlag);
}
String str = sb.toString();
FileUtility.saveStringToFile(filePath, str, false);
}
/**
*
创建装载脚本
* @param conn
* @param creator
表创建者
* @param filePath
*/
private void createLoadFile(Connection conn, String creator,
String filePath) throws
Exception {
DBBase dbBase = new DBBase(conn);
String selectTableSql =
"select name from sysibm.systables where creator = '"
+ creator + "' and type='T' order by name";
try {
dbBase.executeQuery(selectTableSql);
} catch (Exception ex) {
throw ex;
} finally {
dbBase.close();
}
DBResult result = dbBase.getSelectDBResult();
List list = new ArrayList();
while (result.next()) {
String table = result.getString(1);
list.add(table);
}
StringBuffer sb = new StringBuffer();
String enterFlag = "\r\n";
for (int i = 0; i < list.size(); i++) {
String tableName = (String) list.get(i);
sb.append("db2 \"load from aa" + String.valueOf(i + 1)
+ ".ixf of ixf into " + tableName
+ " COPY NO without prompting \"");
sb.append(enterFlag);
}
String str = sb.toString();
FileUtility.saveStringToFile(filePath, str, false);
}
/**
*
获取某个数据库表明的列表
* @param conn
* @param creator
表创建者
* @return
* @throws Exception
*/
private List getTableList(Connection conn, String creator) throws Exception {
DBBase dbBase = new DBBase(conn);
String selectTableSql =
"select name from sysibm.systables where creator = '"
+ creator + "' and type='T' order by name";
try {
dbBase.executeQuery(selectTableSql);
} catch (Exception ex) {
throw ex;
} finally {
dbBase.close();
}
DBResult result = dbBase.getSelectDBResult();
List list = new ArrayList();
while (result.next()) {
String table = result.getString(1);
list.add(table);
}
return list;
}
/**
*
将列表写入到文本文件中
* @param list
* @param filePath
*/
public void saveListToFile(List list, String filePath) throws Exception {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < list.size(); i++) {
String value = (String) list.get(i);
sb.append(value);
sb.append("\r\n");
}
String str = sb.toString();
FileUtility.saveStringToFile(filePath, str, false);
}
posted on 2006-09-14 09:55
水煮三国 阅读(2219)
评论(0) 编辑 收藏 所属分类:
Database