`
namezhou
  • 浏览: 153865 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Java比较两个数据库中所有表的区别【支持Oracle和SQLServer】

 
阅读更多

开发过程中一般是一开发数据库 一生产数据库。

有时候在开发数据库中加了数据库字段之后忘记在生产数据库加字段。

写了工具类,用于比较两个数据库的区别。类似工具Navicat也有这样的功能。

支持自动组装Alter语句追加字段。

Oracle版本:

package dbcom;

import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Oracle 数据库比较
 * @author Eric zhou
 * @since 2013-2-28
 */
public class OracleComparator {
	public static String url1 = "jdbc:oracle:thin:@localhost:1521:SIP";
	public static String url2 = "jdbc:oracle:thin:@localhost:1521:SIP";
	public static String USERNAME = "admin";
	public static String PASSWORD = "root";
	public static boolean auto_syn = true;//自动同步表结构,true 时启用
	public static void main(String[] args) throws Exception{
		OracleComparator com = new OracleComparator();
		Connection con1 = com.getConnection(url1,USERNAME,PASSWORD);
		Connection con2 = com.getConnection(url2,USERNAME,PASSWORD);
		System.out.println("已连接到两个数据库...将以数据库1为主数据库进行比较");
		String sql = "select TABLE_NAME from USER_TABLES";
		List list1 = com.Rs2List(com.getRsBySQL(sql, con1));
		List list2 = com.Rs2List(com.getRsBySQL(sql, con2));
		com.compare(list1, list2,con1,con2);
		System.out.println("比较完成....");
	}
	private void compare(List list1,List list2,Connection con1,Connection con2) throws Exception {
		for (Iterator iterator = list1.iterator(); iterator.hasNext();) {
			String name = (String) iterator.next();
			if(list2.contains(name)){
				this.TableCompare(name, con1, con2);
			}else{
				if(name.indexOf("$")==-1){
					System.out.println("数据库2中,缺少表:"+name);
					if(auto_syn){
						System.out.print("----------------自动创建表"+name+"...");
						System.out.println(createTable(name,con1,con2));
					}
				}
			}
		}
	}
	private void TableCompare(String name,Connection con1,Connection con2) throws Exception {
		String sql = "select COLUMN_NAME,DATA_TYPE from USER_TAB_COLUMNS where TABLE_NAME='"+name+"' ";
		Map<String,String> map1 = this.parseColumnList(this.getRsBySQL(sql, con1));
		Map<String,String> map2 = this.parseColumnList(this.getRsBySQL(sql, con2));
		Set set = map1.keySet();
		for (Iterator iterator = set.iterator(); iterator.hasNext();) {
			String cname = (String) iterator.next();
			if(map2.containsKey(cname)){
				if(!map2.get(cname).equals(map1.get(cname))){
					System.out.println("数据库2的 "+name+" 表中的字段:"+cname+" 与数据库1中数据类型不一致");
					if(auto_syn){
						System.out.println("----------------此项目请手动修改!");
					}
				}
			}else{
				System.out.println("数据库2的 "+name+" 表中,缺少字段:"+cname);
				if(auto_syn){
					System.out.print("----------------自动添加字段"+cname+"...");
					System.out.println(appendColumn(name,cname,con1,con2));
				}
			}
		}
	}
	private Map parseColumnList(ResultSet rs1) throws Exception {
		Map map = new HashMap();
		while(rs1.next()){
			map.put(rs1.getString("COLUMN_NAME"), rs1.getString("DATA_TYPE"));
		}
		return map;
	}
	private List Rs2List(ResultSet rs1)throws Exception{
		List list = new ArrayList();
		while(rs1.next()){
			list.add(rs1.getString("TABLE_NAME"));
		}
		return list;
	}
	private ResultSet getRsBySQL(String sql,Connection con1)throws Exception{
		Statement stmt = con1.createStatement();
		return stmt.executeQuery(sql);
	}
	
	public static String DRIVER = "oracle.jdbc.driver.OracleDriver";
	static {
		try {
			Class.forName(DRIVER).newInstance();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	private Connection getConnection(String url,String username,String password){
		try {
			return DriverManager.getConnection(url,username,password);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return null;
	}
	private String createTable(String name,Connection con1,Connection con2){
		try {
			String sql = "select dbms_metadata.get_ddl('TABLE','"+name+"') as XQL from dual";
			Statement stmt = con1.createStatement();
			ResultSet rs  = stmt.executeQuery(sql);
			if(rs.next()){
				String ddl = rs.getString("XQL");
				Statement stmt2 = con2.createStatement();
				stmt2.execute(ddl);
				return "success";
			}else{
				return "fail";
			}
		} catch (SQLException e) {
			return "fail";
		}
	}
	private String appendColumn(String name,String colname,Connection con1,Connection con2){
		try {
			String sql = "select DATA_TYPE,DATA_LENGTH from USER_TAB_COLUMNS where TABLE_NAME='"+name+"' and COLUMN_NAME='"+colname+"'";
			Statement stmt = con1.createStatement();
			ResultSet rs = stmt.executeQuery(sql);
			if(rs.next()){
				String type = rs.getString("DATA_TYPE");
				BigDecimal b = rs.getBigDecimal("DATA_LENGTH");
				String sql2 = null;
				if(type.contains("CLOB")){
					sql2 = "alter table "+name+" add ( \""+colname+"\" "+type+"  NULL )";
				}else{
					sql2 = "alter table "+name+" add ( \""+colname+"\" "+type+"("+b.intValue()+") NULL )";
				}
				Statement stmt2 = con2.createStatement();
				stmt2.execute(sql2);
				return "success";
			}else{
				return "fail";
			}
		} catch (SQLException e) {
			e.printStackTrace();
			return "fail";
		}
	}
}

 SQLServer版本

 

package dbcom;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * SQL Server 数据库区别比较
 * @author Eric zhou
 * @since 2013-2-28
 */
public class SqlServerComparator {
	public static String url1 = "jdbc:sqlserver://localhost:1433;DatabaseName=xx1";
	public static String url2 = "jdbc:sqlserver://localhost:1433;DatabaseName=xx1";
	public static String USERNAME = "sa";
	public static String PASSWORD = "123";
	
	public static void main(String[] args) throws Exception{
		SqlServerComparator com = new SqlServerComparator();
		Connection con1 = com.getConnection(url1,USERNAME,PASSWORD);
		Connection con2 = com.getConnection(url2,USERNAME,PASSWORD);
		System.out.println("已连接到两个数据库...将以数据库1为主数据库进行比较");
		String sql = "select name from sys.all_objects where type_desc='USER_TABLE'";
		List list1 = com.Rs2List(com.getRsBySQL(sql, con1));
		List list2 = com.Rs2List(com.getRsBySQL(sql, con2));
		com.compare(list1, list2,con1,con2);
		System.out.println("比较完成....");
	}
	private void compare(List list1,List list2,Connection con1,Connection con2) throws Exception {
		for (Iterator iterator = list1.iterator(); iterator.hasNext();) {
			String name = (String) iterator.next();
			if(list2.contains(name)){
				this.TableCompare(name, con1, con2);
			}else{
				System.out.println("数据库2中,缺少表:"+name);
			}
		}
	}
	private void TableCompare(String name,Connection con1,Connection con2) throws Exception {
		String sql = "select c.name,c.system_type_id from sys.all_columns c left join  sys.all_objects o on c.object_id=o.object_id where o.name='"+name+"' ";
		Map<String,Integer> map1 = this.parseColumnList(this.getRsBySQL(sql, con1));
		Map<String,Integer> map2 = this.parseColumnList(this.getRsBySQL(sql, con2));
		Set set = map1.keySet();
		for (Iterator iterator = set.iterator(); iterator.hasNext();) {
			String cname = (String) iterator.next();
			if(map2.containsKey(cname)){
				if(map2.get(cname).intValue()!=map1.get(cname).intValue()){
					System.out.println("数据库2的 "+name+" 表中的字段:"+cname+" 与数据库1中数据类型不一致");
				}
			}else{
				System.out.println("数据库2的 "+name+" 表中,缺少字段:"+cname);
			}
		}
	}
	private Map parseColumnList(ResultSet rs1) throws Exception {
		Map map = new HashMap();
		while(rs1.next()){
			map.put(rs1.getString("name"), rs1.getInt("system_type_id"));
		}
		return map;
	}
	private List Rs2List(ResultSet rs1)throws Exception{
		List list = new ArrayList();
		while(rs1.next()){
			list.add(rs1.getString("name"));
		}
		return list;
	}
	private ResultSet getRsBySQL(String sql,Connection con1)throws Exception{
		Statement stmt = con1.createStatement();
		return stmt.executeQuery(sql);
	}
	
	public static String DRIVER = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
	static {
		try {
			Class.forName(DRIVER).newInstance();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	private Connection getConnection(String url,String username,String password){
		try {
			return DriverManager.getConnection(url,username,password);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return null;
	}
}

 

1
0
分享到:
评论

相关推荐

    Oracle,Mysql,SqlServer三大主流数据库驱动(全包含)

    压缩包里包含的是这三大主流数据库的驱动,其中SqlServer包含了两个版本,看文件名就明白了,是2000和2005的!其余两个是Oracle和Mysql的。其中还附有一个txt文档,写明了常用的数据库连接语法!

    实体类生成器

    支持数据库oracle 和 SqlServer 支持实体类生成程序:C# 和 java *注意: 电脑上一定要安装 framework才能运行本软件 有什么问题请联系qq:910579826 备注添加:实体类生成器 1. 用户首先选择要操作的数据库,选中...

    SQL编写规范(数据库操作规范)

     EXPLAIN PLAN的分析结果是用缩进的格式排列的,最内部的操作将最先被解读,如果两个操作处于同一层中,带有最小操作号的将首先被执行    目前许多第三方的工具如PLSQL Developer和TOAD等都提供了极其方便的...

    database-sync:数据库表同步程序,支持不同数据库间表结构和数据的同步,数据抽取

    支持主流的关系型数据库:mysql,db2,postgresql,oracle,sqlserver 本程序由java编写,基于1.8版本,方便打包移植。本程序的最大用处就是生成集市或数仓所需要的基础层数据源。 简单的预期一定的参数,即可跨...

    oracle数据库经典题目

    18. 表空间是Oracle数据库中数据的逻辑组织,每个数据库至少有一个SYSTEM系统表空间。 19.视图是一个表示表的数据的数据库对象,它允许用户从一个表或一组表中通过一定的查询语句建立一个“虚表”。 20.序列是一种...

    oracle迁移达梦常见问题汇总

    其中对于出错的任务,主要有导表和导函数包两部分。其中主要棘手的在与迁移函数包等对象时的问题。 2、迁移错误详解 2.1、通用问题 说明:对于直接使用DTS迁移失败的包,最好从源端获取完整的定义,重新核查报错...

    java程序是怎么操作数据库的,可以以常用据库为例,求详细解答,最好能举例。

    在上面这个程序中我想你展示了如何使用JDBC-ODBC连接数据库,使用SQL语句生成一个表,使用SELECT、INSERT 、UPDATE语句取的、插入和更新一个表中的数据,如何通过字段名和字段索引访问数据库中的东东!我希望你能从...

    Java高级程序设计实战教程第八章-Java数据库编程.pptx

    一般来说,访问数据库中的数据有两种方式: 一是通过DBMS(Data Base Management System,数据库管理系统)提供的数据库操作工具来访问,如通过SQL Server 2000的查询设计器来提交查询,或者通过SQL Server ...

    JAVA_JSP_sql server企业合同管理系统设计软件源码+数据库+WORD毕业论文文档.zip

    JAVA_JSP_sql server企业合同管理系统设计软件源码+数据库+WORD毕业论文文档: JAVA_JSP企业合同管理系统主要用于实现企业合同的管理, 基本功能包括:修改个人密码、合同信息管理、收款提醒模块、安全退出系统等。...

    JSP+Oracle图书管理系统

    1.将JAVAMailWeb\database\javaemail.mdf以及javaemail.mdf这两个数据库附加到SQLServer 2005中 2.将JAVAMailWeb整个文件夹复制到MyEclipse的“个人工作空间(WorkSpace)”。 3.启动MyEclipse,新建一个JavaProject,...

    JEECG切换数据库方法

    JEECG切换数据的方法,可选数据有 ORACLE、MySql、Sql Server等

    ODI代理找不到驱动

    两个文件夹的放置意图是不同的,对于ODI的服务器端,可将驱动放在&lt;ODI_HOME&gt;\agent\drivers下,当进行数据库连接时,自动会调用服务器端的驱动,而用于连服务器的客户端,由于它们是没有&lt;ODI_HOME&gt;\oracledi\agent\...

    ADO连接数据库.pdf

    ADO 数据库编程 中大型的数据库管理信息系统(MIS)的开发,一般很少...ODBC 工作依赖于数据库制造商(MS SQL Server, Oracle,Sybase 等) 提供的驱动程序。使用 ODBC API 的时候,Windows 的 ODBC 管理程序,把对数据库

    metadata:oracle,mysql,sql server 元数据管理表生成

    作用:可以自动将所有的表信息和字段信息存入元数据表中,便于统一查阅。(注释需要保证库本身已经包含了对于表和字段的注释)方式用于为数据库提供两张表。 meta_field, meta_model。表名称说明meta_model用于存放...

    JAVA上百实例源码以及开源项目

     基于JAVA的UDP服务器模型源代码,内含UDP服务器端模型和UDP客户端模型两个小程序,向JAVA初学者演示UDP C/S结构的原理。 简单聊天软件CS模式 2个目标文件 一个简单的CS模式的聊天软件,用socket实现,比较简单。 ...

    JAVA上百实例源码以及开源项目源代码

     基于JAVA的UDP服务器模型源代码,内含UDP服务器端模型和UDP客户端模型两个小程序,向JAVA初学者演示UDP C/S结构的原理。 简单聊天软件CS模式 2个目标文件 一个简单的CS模式的聊天软件,用socket实现,比较简单。 ...

    oracle应用服务器.pptx

    开发工具 Web/运用开发工具 要将Web运用运用于拥有Web阅读器的用户,只需求一个Web/运用效劳器和一个数据库效劳器就可以,但是,在这之前,需求一些工具来停止运用开发 Java 工具 PL/SQL工具 Oracle Designer ...

Global site tag (gtag.js) - Google Analytics