java - 如何比较两个不同数据库用户之间的架构?
问题描述
我正在开发一个自定义 nifi 处理器来比较 Oracle DB 中两个不同数据库用户的模式。所以这个自定义的 nifi 处理器将能够验证不同数据库用户之间的模式,如果我们必须选择一个用户作为源,另一个用户作为目标。
如果源具有目标中不可用的表,则处理器将为该表生成创建脚本。如果源和目标具有相同名称的表,则它将比较列。
如果源表的列名在目标表中不存在,处理器将生成一个更改脚本(ADD)。如果存在相同的列,那么它将比较数据类型和长度。如果数据类型和长度不匹配,处理器将生成另一个更改脚本(修改)。
我这样做的方法是,从表 user_tab_columns 中获取表详细信息,它将给出所有列名、数据类型、数据长度、精度、比例等。
所以我会为我的两个数据库用户做同样的方法。然后我将比较源和目标的每一个值,如果不匹配,我将执行所需的操作。
我只是想知道,是否有不同的方法可以在不同的数据库用户之间执行模式比较,以及如何改进当前的方法。
private void validateCurrentTable(XelerateJsonTableDetail currentTable,DataValidationDetails dataValidationDetails) throws SQLException {
boolean isDataAvailable = true;
boolean validationFlag;
List<DataValidationMetaDetails> sourceMetaDetailsList = new ArrayList<DataValidationMetaDetails>();
List<DataValidationMetaDetails> targetMetaDetailsList = new ArrayList<DataValidationMetaDetails>();
ResultSet metaDataSource = getColumns(sourceConnection,currentTable.getTableName());
while(isDataAvailable){
DataValidationMetaDetails sourceMetaDetails = new DataValidationMetaDetails() ;
if(!metaDataSource.next()){
isDataAvailable = false;
}else{
sourceMetaDetails.settableName(metaDataSource.getString("TABLE_NAME"));
sourceMetaDetails.setColumnName(metaDataSource.getString("COLUMN_NAME"));
sourceMetaDetails.setdataType(metaDataSource.getString("DATA_TYPE"));
sourceMetaDetails.setdataLength(metaDataSource.getString("DATA_LENGTH"));
sourceMetaDetails.setdataPrescision(checkNull(metaDataSource.getString("DATA_PRECISION")));
sourceMetaDetails.setdataScale(checkNull(metaDataSource.getString("DATA_SCALE")));
if("C".equals(metaDataSource.getString("CHAR_USED"))){
sourceMetaDetails.setDataCharLength(metaDataSource.getString("CHAR_LENGTH"));
sourceMetaDetails.setDataCharUsed(metaDataSource.getString("CHAR_USED"));
}
sourceMetaDetailsList.add(sourceMetaDetails);
}
}
isDataAvailable = true;
ResultSet metaDataTarget = getColumns(targetConnection,currentTable.getTableName());
while(isDataAvailable){
DataValidationMetaDetails targetMetaDetails = new DataValidationMetaDetails() ;
if(!metaDataTarget.next()){
isDataAvailable = false;
}else{
targetMetaDetails.settableName(metaDataTarget.getString("TABLE_NAME"));
targetMetaDetails.setColumnName(metaDataTarget.getString("COLUMN_NAME"));
targetMetaDetails.setdataType(metaDataTarget.getString("DATA_TYPE"));
targetMetaDetails.setdataLength(metaDataTarget.getString("DATA_LENGTH"));
targetMetaDetails.setdataPrescision(checkNull(metaDataTarget.getString("DATA_PRECISION")));
targetMetaDetails.setdataScale(checkNull(metaDataTarget.getString("DATA_SCALE")));
if("C".equals(metaDataTarget.getString("CHAR_USED"))){
targetMetaDetails.setDataCharLength(metaDataTarget.getString("CHAR_LENGTH"));
targetMetaDetails.setDataCharUsed(metaDataTarget.getString("CHAR_USED"));
}
targetMetaDetailsList.add(targetMetaDetails);
}
}
validationFlag = compareSchema(sourceMetaDetailsList,targetMetaDetailsList);
}
private boolean compareSchema(List<DataValidationMetaDetails> sourceMetaDetailsList, List<DataValidationMetaDetails> targetMetaDetailsList) {
Map<String,DataValidationMetaDetails> schemaMap = new HashMap<String,DataValidationMetaDetails>();
DataValidationMetaDetails mapMetaDeatils = new DataValidationMetaDetails();
for(DataValidationMetaDetails metaDeatils : targetMetaDetailsList){
schemaMap.put(metaDeatils.getColumnName(), metaDeatils);
}
for(DataValidationMetaDetails metaDeatils : sourceMetaDetailsList){
if(null!=schemaMap.get(metaDeatils.getColumnName())){
mapMetaDeatils = schemaMap.get(metaDeatils.getColumnName());
if(mapMetaDeatils.getdataType().equals(metaDeatils.getdataType())){
if(!mapMetaDeatils.getdataLength().equals(metaDeatils.getdataLength())){
if(!mapMetaDeatils.getdataPrescision().equals(metaDeatils.getdataPrescision())){
if(!mapMetaDeatils.getdataScale().equals(metaDeatils.getdataScale())){
String dataTypeMod = "";
genAlterModifyScript(metaDeatils,"");
}
}else{
}
}else{
genAlterModifyScript(metaDeatils,"L");
}
}else{
logger.info("Data Type Mismatch for the Column : "+metaDeatils.getColumnName());
}
}else{
genAlterAddScript(metaDeatils);
}
}
return false;
}
private void genAlterModifyScript(DataValidationMetaDetails metaDeatils,String flag) {
alterModifyQuery.append("\n");
alterModifyQuery.append("ALTER TABLE ");
alterModifyQuery.append(metaDeatils.gettableName());
alterModifyQuery.append(" MODIFY ");
alterModifyQuery.append(metaDeatils.getColumnName());
switch(flag){
case "L" : alterModifyQuery.append("("+metaDeatils.getdataLength()+")");
break;
case "P" : alterModifyQuery.append("("+metaDeatils.getdataPrescision()+","+metaDeatils.getdataScale()+")");
break;
case "S" : alterModifyQuery.append("("+metaDeatils.getdataPrescision()+","+metaDeatils.getdataScale()+")");
break;
}
}
解决方案
在 Oracle 中,您可以通过执行以下操作找到 SCHEMA_1 和 SCHEMA_2 之间的表不匹配:
SELECT *
FROM DBA_TABLES t1
WHERE t1.OWNER = 'SCHEMA_1'
MINUS
SELECT *
FROM DBA_TABLES t2
WHERE t2.OWNER = 'SCHEMA_2';
同样,要查找列不匹配,您可以使用
SELECT c1.COLUMN_NAME,
c1.DATA_TYPE
FROM DBA_TAB_COLS c1
WHERE c1.OWNER = 'SCHEMA_1' AND
c1.TABLE_NAME IN (SELECT t2.TABLE_NAME
FROM DBA_TABLES t2
WHERE t2.OWNER = 'SCHEMA_2')
MINUS
SELECT c2.COLUMN_NAME,
c2.DATA_TYPE
FROM DBA_TAB_COLS c2
WHERE c2.OWNER = 'SCHEMA_2' AND
c2.TABLE_NAME IN (SELECT t1.TABLE_NAME
FROM DBA_TABLES t1
WHERE t1.OWNER = 'SCHEMA_1')
调整它以比较您想要比较的任何其他内容。通过查询正确的 DBA 视图和字段,您可以很容易地将其扩展到其他数据库对象。
推荐阅读
- java - Dijkstra算法,试图在最短路径中找到第一个节点
- c# - Visual Studio 2017,新建项目时默认使用新样式csproj
- salt-stack - SaltStack:模块文件。查找名称参数
- android - 具有基于响应的动态元素的 RecyclerView
- system-verilog - 使用可综合 System-Verilog 中的参数来声明任意常量的宽度
- amazon-web-services - 如何检查 Amazon Linux 机器 (AMI) 上的 Tomcat 版本?
- c# - 如何在 c# 脚本中对 UnityEnine.Input 进行分类
- html - 不显示带有标签的下拉列表项
- android - @style 属性在 api 24 及更低版本上崩溃
- sqlite - SQLite VACUUM 使用哪个临时目录