Java对比两个数据库中的表和字段,写个冷门的东西

转载的 来源网络

目前所在的项目组距离下个版本上线已经很近了,就面临了一个问题:开发人员在开发库上根据需要增加数据表数据字段、或者变更了字段类型或者字段长度等等。

由于时间比较紧迫,导致在开发过程中不可能一一把DDL数据库脚本记录下来,在比较大的项目中,比如我所在项目开发的系统大概包含了800张左右的表,字段上10000个的情况下,人工处理明显不可行,所以我们就得通过程序来判断比对,哪些是我们需要新增加的表,哪些是我们需要新增加的字段,哪些是我们需要修改的字段。

因为我开发的项目是为银行工作的,所以数据量无疑很大,所以这个Java类可以用于几乎大多数情况了,当前情况是正在运行的生产服务器上有个数据库-->生产库,我们开发人员服务器上有个数据库-->开发库,就需要我们将两库差异对比出来,我差不多花了1个小时写了下面几个类,运行一下就可以将差异化的地方写入文件中,便于后续写DDL脚本处理。

首先是一个 Table 类,代表了我们数据库中的一张表,其中存在String类型的表名、和存放若干个各种字段的HashMap()

 
 
 
 

Java

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package test;
import java.util.HashMap;
public class Table {
public String tableName;
public HashMap columns = new HashMap();
 
public Table(String tableName) {
this.tableName = tableName;
}
 
public String getTableName() {
return tableName;
}
 
public void setTableName(String tableName) {
this.tableName = tableName;
}
 
public HashMap getColumns() {
return columns;
}
 
public void setColumns(HashMap columns) {
this.columns = columns;
}
}

接着就是一个 Column 类,代表了数据库中的一个字段,其中属性就是字段名、字段类型、字段长度,当然可以根据自己的需求加入更多要素

 
 
 
 

Java

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package test;
public class Column {
public String columnName;
public String dataType;
public int length;
 
public Column(String columnName, String dataType, int length) {
this.columnName = columnName;
this.dataType = dataType;
this.length = length;
}
public String getColumnName() {
return columnName;
}
public void setColumnName(String columnName) {
this.columnName = columnName;
}
public String getDataType() {
return dataType;
}
public void setDataType(String dataType) {
this.dataType = dataType;
}
public int getLength() {
return length;
}
public void setLength(int length) {
this.length = length;
}
}

其实这个方法完全可以不用上面两个类的,但是为了写起来理解方便,所以就用了,执行效率其实还不错,几百张表几秒钟就跑完了

下面是实现这个需求的主要类,写出来的主要目的就是希望能帮我改进一下,毕竟自己写程序没有太多的设计理念和大局观,希望能者修改修改:

 
 
 
 

Java

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
package test;
package test;
 
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
 
import com.amarsoft.are.sql.ASResultSet;
import com.amarsoft.are.sql.Transaction;
import com.amarsoft.are.util.DataConvert;
 
public class CompareTable {
 
public static StringBuffer[] sb = { new StringBuffer(), new StringBuffer(),
new StringBuffer(), new StringBuffer(), new StringBuffer(),
new StringBuffer() };
 
public static Transaction getTransaction_product() throws Exception {
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn = DriverManager.getConnection(
"jdbc:oracle:thin:@192.168.1.1:1621:orcl", "demo1", "demo1");
if (conn != null)System.out.println("数据库加载成功!");
Transaction transaction = new Transaction(conn);
return transaction;
}
 
public static Transaction getTransaction_develop() throws Exception {
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn = DriverManager.getConnection(
"jdbc:oracle:thin:@192.168.1.2:1621:orcl", "demo2", "demo2");
if (conn != null)System.out.println("数据库加载成功!");
Transaction transaction = new Transaction(conn);
return transaction;
}
 
public static void main(String[] args) throws Exception {
compareTables(); // 比较数据库
writeFile(); // 写入文件
}
 
 
 
public static void compareTables() throws Exception {
 
// 生产数据库连接
Transaction trans_product = getTransaction_product();
Map<</SPAN>String, Table> map_product = getTables(trans_product);
 
// 开发数据库连接
Transaction trans_develop = getTransaction_develop();
Map<</SPAN>String, Table> map_develop = getTables(trans_develop);
 
// 遍历开发库Map
for (Iterator iter_table = map_develop.keySet().iterator(); iter_table
.hasNext();) {
String key_table = (String) iter_table.next();
Table table_develop = map_develop.get(key_table);// 获得开发库中的表
Table table_product = map_product.get(key_table);// 尝试从生产库中获得同名表
if (table_product == null) { // 如果获得表为空,说明开发存在,生产不存在
append(table_develop, null, 2);
} else { // 表相同,判断字段、字段类型、字段长度
for (Iterator iter_column = table_develop.columns
.keySet().iterator(); iter_column.hasNext();) {
String key_column = (String) iter_column.next();
Column column_develop = table_develop.columns.get(key_column);// 获得开发库中的列
Column column_product = table_product.columns.get(key_column);// 尝试从生产库中获得同名列
if (column_product == null) {// 如果列名为空,说明开发存在,生产不存在
append(table_develop, column_develop, 4);
} else {// 说明两者都存在
if (!column_develop.dataType.equals(column_product.dataType))// 字段类型不一致
append(table_develop, column_develop, 5);
if (column_develop.length != column_product.length)// 字段长度不一致
append(table_develop, column_develop, 6);
}
}
}
}
 
// 遍历生产库Map
for (Iterator iter_table = map_product.keySet().iterator(); iter_table
.hasNext();) {
String key_table = (String) iter_table.next();
Table table_product = map_product.get(key_table);// 尝试从生产库中获得同名表
Table table_develop = map_develop.get(key_table);// 获得开发库中的表
if (table_develop == null) { // 如果获得表为空,说明开发存在,生产不存在
append(table_product, null, 1);
} else { // 表相同,判断字段、字段类型、字段长度
for (Iterator iter_column = table_product.columns
.keySet().iterator(); iter_column.hasNext();) {
String key_column = (String) iter_column.next();
Column column_product = table_product.columns.get(key_column);// 获得生产库中的列
Column column_develop = table_develop.columns.get(key_column);// 尝试从开发库中获得同名列
if (column_develop == null) {// 如果列名为空,说明生产存在,开发不存在
append(table_product, column_product, 3);
}
}
}
}
}
 
 
public static Map<</SPAN>String, Table> getTables(Transaction transaction)
throws Exception {
 
String sSql = " select table_name,Column_Name,Data_Type,"
+ " DECODE(DATA_TYPE,'NUMBER',DATA_PRECISION,'VARCHAR2',"
+ " DATA_LENGTH,'VARCHAR',DATA_LENGTH,'CHAR',DATA_LENGTH,0) Length,"
+ " NVL(DATA_SCALE, 0) SCALE,DECODE(NULLABLE, 'N', '1', '0') NULLABLE "
+ " from user_tab_columns where 1=1 Order By table_name,column_name";
 
ASResultSet rs = transaction.getASResultSet(sSql);
 
Map<</SPAN>String, Table> map = new HashMap<</SPAN>String, Table>();
 
String tableName = "";
Table table = null;
while (rs.next()) {
if (!tableName.equals(rs.getString("table_name"))) {// 一张新表
tableName = rs.getString("table_name");
table = new Table(tableName);
Column column = new Column(rs.getString("Column_Name"),
rs.getString("Data_Type"), rs.getInt("Length"));
table.columns.put(column.columnName, column);
map.put(rs.getString("table_name"), table);
} else {// 已存在的表,增加字段
Column column = new Column(rs.getString("Column_Name"),
rs.getString("Data_Type"), rs.getInt("Length"));
table.columns.put(column.columnName, column);
}
}
if (null != rs)
rs.close();
transaction.finalize();
return map;
}
 
 
public static void append(Table table, Column column, int flag)
throws Exception {
switch (flag) {
case 1:
System.out.println("1、生产存在,开发不存在的表:" + table.getTableName());// 跳过
sb[0].append(table.getTableName() + "\n");
break;
case 2:
System.out.println("2、生产不存在,开发存在的表:" + table.getTableName());// 需要人工判断脚本
sb[1].append(table.getTableName() + "\n");
break;
case 3:
System.out.println("3、生产存在,开发不存在的字段:" + table.getTableName()
+ " | " + column.getColumnName());// 需人工判断如何处理
sb[2].append(table.getTableName() + " | " + column.getColumnName()
+ "\n");
break;
case 4:
System.out.println("4、生产不存在,开发存在的字段:" + table.getTableName()
+ " | " + column.getColumnName());// 需要人工判断脚本
sb[3].append(table.getTableName() + " | " + column.getColumnName()
+ "\n");
break;
case 5:
System.out.println("5、表和字段都相同,但字段类型不同的内容:" + table.getTableName()
+ " | " + column.getColumnName() + " | "
+ column.getDataType());// 需要人工判断脚本
sb[4].append(table.getTableName() + " | " + column.getColumnName()
+ " | " + column.getDataType() + "\n");
break;
case 6:
System.out.println("6、表和字段、字段类型都相同,但字段长度不同的内容:"
+ table.getTableName() + " | " + column.getColumnName()
+ " | " + column.getLength());// 需要人工判断脚本
sb[5].append(table.getTableName() + " | " + column.getColumnName()
+ " | " + column.getLength() + "\n");
break;
}
}
 
 
public static void writeFile() throws Exception {
String[] fileName = { "D://table//生产存在,开发不存在的表.txt",
"D://table//生产不存在,开发存在的表.txt", "D://table//生产存在,开发不存在的字段.txt",
"D://table//生产不存在,开发存在的字段.txt",
"D://table//表和字段都相同,但字段类型不同的内容.txt",
"D://table//表和字段、字段类型都相同,但字段长度不同的内容.txt" };
 
for (int i = 0; i <</SPAN> fileName.length; i++) {
File file = new File(fileName[i]);
OutputStream os = new FileOutputStream(file);
os.write(sb[i].toString().getBytes());
os.flush();
os.close();
}
}
}

尾声:整个程序其实并不复杂,感觉被我写得有些累赘了,希望以后能精简一点吧

分享:   

Java对比两个数据库中的表和字段,写个冷门的东西的更多相关文章

  1. 使用sql查询mysql/oracle/sql server/gp数据库中指定表的字段信息(字段名/字段类型/字段长度/是否是主键/是否为空)

    1,根据数据库类型拼接不同URL /** * 根据类型不同拼接连接的URL * @param dbType 1:mysql.2:oracle.3:sql server.4:gp * @param ip ...

  2. 【转】 mysql使用federated引擎实现远程访问数据库(跨网络同时操作两个数据库中的表)

    原文转自:http://www.2cto.com/database/201412/358397.html 问题: 这里假设我需要在IP1上的database1上访问IP2的database数据库内的t ...

  3. WordPress数据库中的表、字段、类型及说明

    wp_categories: 用于保存分类相关信息的表.包括了5个字段,分别是: cat_ID – 每个分类唯一的ID号,为一个bigint(20)值,且带有附加属性auto_increment. c ...

  4. mysql查同个实例两个数据库中的表名差异

    select TABLE_NAME from ( select TABLE_NAME ,) as cnt from information_schema.tables where TABLE_SCHE ...

  5. 获取SQL Server数据库中的表和字段描述

    获取所有dbo表的扩展属性: SELECT * FROM fn_listextendedproperty (NULL, 'schema', 'dbo', 'table', default, NULL, ...

  6. MySql 查询数据库中所有表名以及对比分布式库中字段和表的不同

    查询数据库中所有表名select table_name from information_schema.tables where table_schema='数据库名' and table_type= ...

  7. 两种获取MySql数据库中所有表的主键和外键约束信息的Sql语句

    最近在写Rafy底层的一些东西,在数据库方面把MySql数据库集成到里面去,里面有一个需求,需要获取非系统数据库,也就是我们自己建立的数据库中所有表的主键和外键元数据列表. 第一种方法:是网上的方法, ...

  8. 点评阿里JAVA手册之MySQL数据库 (建表规约、索引规约、SQL语句、ORM映射)

    下载原版阿里JAVA开发手册  [阿里巴巴Java开发手册v1.2.0] 本文主要是对照阿里开发手册,注释自己在工作中运用情况. 本文内容:MySQL数据库 (建表规约.索引规约.SQL语句.ORM映 ...

  9. 通过jdbc获取数据库中的表结构

    通过jdbc获取数据库中的表结构 主键 各个表字段类型及应用生成实体类   1.JDBC中通过MetaData来获取具体的表的相关信息.可以查询数据库中的有哪些表,表有哪些字段,字段的属性等等.Met ...

随机推荐

  1. 2.4G芯片

    一 南京中科微: Si24R1GFSK无线收发芯片    Si24R1专为低功耗无线通信应用场合设计.工作频率为2400MHz-2525MHz,共有126个1MHz带宽的信道:典型应用:有源RFID. ...

  2. 通过aptitude降级包解决依赖问题(E:无法修正错误,因为您要求某些软件包保持现状)

    Linux下的依赖关系令人头疼,尤其是提示如下错误的时候: 下列软件包有未满足的依赖关系: xxx : 依赖: xxx 但是它将不会被安装 E: 无法修正错误,因为您要求某些软件包保持现状,就是它们破 ...

  3. Android抓包分析-fiddler版

    本文介绍的是如何使用Fiddler工具抓取Android应用的HTTP协议的数据包 工具 Genymotion模拟器 笔记本电脑一台(Win7) Fiddler(v4.6.2),下载地址:http:/ ...

  4. Jquery+ajax模板

    $.ajax({     url:'',     type:'POST', //GET     async:true,    //或false,是否异步     data:{         name ...

  5. PAT A1114 Family Property

    用并查集处理每个家庭的信息,注意标记~ #include<bits/stdc++.h> using namespace std; ; bool visit[maxn]={false}; i ...

  6. Assign the task-HDU3974 dfs序+线段树

    题意: 一个公司有n个员工,每个员工都有一个上司,一个人下属的下属也是这个人的下属,因此可将他们的关系看成一棵树, 然后给定两种操作,C操作是查询当前员工的工作,T操作是将y工作分配给x员工,当一个人 ...

  7. 吴裕雄 Bootstrap 前端框架开发——Bootstrap 表格:为任意 <table> 添加基本样式 (只有横向分隔线)

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  8. 吴裕雄 Bootstrap 前端框架开发——Bootstrap 排版:可滚动

    <!DOCTYPE html> <html> <head> <title>菜鸟教程(runoob.com)</title> <meta ...

  9. 3_03_MSSQL课程_Ado.Net_数据导入

    数据库数据导出和导入 思路: --思路: 1.找到文件 2.读取文件 3.第一行 忽略 4.insert using System; using System.Collections.Generic; ...

  10. C 语言入门第十二章---C语言文件操作

    C语言具有操作文件的能力,比如打开文件.读取和追加数据.插入和删除数据.关闭文件.删除文件等. 在操作系统中,为了同意对各种硬件的操作,简化接口,不同的硬件设备也都被看成一个文件.对这些文件的操作,等 ...