Oralce数据库结构对比程序
2012-06-02 15:19:22 来源:WEB开发网核心提示:因为在系统中,一个业务数据库往往存在多份物理数据库,比如开发数据库,测试数据库和生产数据库,加上还有一些其它用途的数据库,要维持这些数据库之间的结构统一也不是很容易,所以自己弄了个简单的数据库表结构对比程序,用来分析各个数据库之间的差异.这里只是简单的比较,其实在这个基础上还可以做差异自动修复.下面是代码:/建立一个对
因为在系统中,一个业务数据库往往存在多份物理数据库,比如开发数据库,测试数据库和生产数据库,加上还有一些其它用途的数据库,要维持这些数据库之间的结构统一也不是很容易,所以自己弄了个简单的数据库表结构对比程序,用来分析各个数据库之间的差异.这里只是简单的比较,其实在这个基础上还可以做差异自动修复.下面是代码:
/建立一个对比结果数据集,两列,结果含义为: //第1列,第2列 含义 // 空 非空 第2列所示表字段在第1个数据库中不存在 // 非空 空 第1列所示表字段在第2个数据库中不存在 // 非空 非空 两个数据库表和字段相同,但数据类型有差异 // 空 空 表示两个数据库中表和字段可以对应,但这类结果不保存. DataTable theTable = new DataTable(); theTable.Columns.Add(new DataColumn("Database1",typeof(string))); theTable.Columns.Add(new DataColumn("Database2",typeof(string))); //获取Oracle中所有当前用户拥有的表和字段名,及其数据类型和数据长度,这里没有考虑精度,注意一定要排序,否则必对算法比较麻烦. string theSQL =@"select t2.TNAME,t1.COLUMN_NAME,t1.DATA_TYPE,t1.DATA_LENGTH from user_tab_columns t1,tab t2 where t1.TABLE_NAME = t2.tname and t2.tabtype='TABLE' order by t2.tname,t1.COLUMN_NAME"; //DataHelper.QueryDataFromDb()就是简单的查询语句执行,这个函数很简单. DataTable theTabs1 = DataHelper.QueryDataFromDb(theSQL, "数据库连接串"); DataTable theTabs2 = DataHelper.QueryDataFromDb(theSQL, "数据库连接串"); int theCount1=0; int theCount2 = 0; //进行比对. while (theCount1 < theTabs1.Rows.Count && theCount2 < theTabs2.Rows.Count ) { DataRow theRow1 = theTabs1.Rows[theCount1]; DataRow theRow2 = theTabs2.Rows[theCount2]; string theTabName1 = theRow1["TNAME"].ToString(); string theCol1 = theRow1["COLUMN_NAME"].ToString(); string theType1 = theRow1["DATA_TYPE"].ToString(); int theLen1 = int.Parse(theRow2["DATA_LENGTH"].ToString()); string theTabName2 = theRow2["TNAME"].ToString(); string theCol2 = theRow2["COLUMN_NAME"].ToString(); string theType2 = theRow2["DATA_TYPE"].ToString(); int theLen2 = int.Parse(theRow2["DATA_LENGTH"].ToString()); int theRet1 = String.Compare(theTabName1,theTabName2); //先比对表,如果表名不相等,因为已经排序,则说明“小的”在另外一方数据中不存在,小的一方索引增加. //如果相等则继续比较字段. if(theRet1 > 0) { DataRow theRetRow = theTable.NewRow(); theTable.Rows.Add(theRetRow); theRetRow[1] = "\r\n"+theTabName2+" " + theCol2; theCount2++; continue; } if(theRet1<0) { DataRow theRetRow = theTable.NewRow(); theTable.Rows.Add(theRetRow); theRetRow[0] = "\r\n"+theTabName1+" " + theCol1; theCount1++; continue; } //表名相同,比较字段,因为已经排序,则说明字段“小的”在另外一方数据中不存在,小的一方索引增加. //如果相等则继续比较数据类型和数据长度. int theRet2 = String.Compare(theCol1,theCol2); if(theRet2 > 0) { DataRow theRetRow = theTable.NewRow(); theTable.Rows.Add(theRetRow); theRetRow[1] = "\r\n"+theTabName2+" " + theCol2; theCount2++; continue; } if(theRet2<0) { DataRow theRetRow = theTable.NewRow(); theTable.Rows.Add(theRetRow); theRetRow[0] = "\r\n"+theTabName1+" " + theCol1; theCount1++; continue; } //如果类型或者长度不一致,则都输出。 if ( theType1 != theType2 || theLen1 != theLen2) { DataRow theRetRow = theTable.NewRow(); theTable.Rows.Add(theRetRow); theRetRow[0] = "\r\n"+theTabName1+" " + theCol1+" "+theType1+" "+theLen1.ToString(); theRetRow[1] = "\r\n"+theTabName2+" " + theCol2+" "+theType2+" "+theLen2.ToString(); } theCount1++; theCount2++; } //这种对比方式下,会产生一方已经到头,另一方还存在未比对的数据,则只要直接输出即可。 while (theCount1 < theTabs1.Rows.Count) { DataRow theRetRow = theTable.NewRow(); theTable.Rows.Add(theRetRow); DataRow theRow1 = theTabs1.Rows[theCount1]; theRetRow[0] = "\r\n" + theRow1["TNAME"].ToString() + " " + theRow1["COLUMN_NAME"].ToString(); theCount1++; } while (theCount2 < theTabs1.Rows.Count) { DataRow theRetRow = theTable.NewRow(); theTable.Rows.Add(theRetRow); DataRow theRow2 = theTabs1.Rows[theCount2]; theRetRow[1] = "\r\n" + theRow2["TNAME"].ToString() + " " + theRow2["COLUMN_NAME"].ToString(); theCount2++; } //与数据库打交道,这里我用的是odp.net. public class DataHelper { public static DataTable QueryDataFromDb(string Sql, string ConnStr) { OracleConnection theConn = new OracleConnection(ConnStr); OracleDataAdapter theDA = new OracleDataAdapter(Sql, theConn); DataSet theDs = new DataSet(); theDA.Fill(theDs); theDA.Dispose(); theConn.Close(); return theDs.Tables[0]; } }
PS:其实从这个小程序也可以看出排序的重要性,因为数据一旦排序,很多处理就非常方便。如果两边结果都没有排序的话,时间复杂度会很高。上述算法的时间复杂度为O(m+n).如果没有排序,就可能达到o(m*n).
更多精彩
赞助商链接