【问题标题】:How to compare schema between two different database users?如何比较两个不同数据库用户之间的架构?
【发布时间】:2019-06-26 11:06:11
【问题描述】:

我正在开发一个自定义 nifi 处理器来比较 Oracle DB 中两个不同数据库用户的架构。所以这个自定义的 nifi 处理器将能够验证不同 db 用户之间的模式,如果我们必须选择一个用户作为源,另一个用户作为目标。

如果源具有目标中不可用的表,则处理器将为该表生成创建脚本。如果源和目标具有相同名称的表,则它将比较列。

如果源表的列名在目标表中不存在,处理器将生成一个更改脚本(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;
    }
}

【问题讨论】:

    标签: java oracle apache-nifi


    【解决方案1】:

    在 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 视图和字段,您可以很容易地将其扩展到其他数据库对象。

    【讨论】:

    • 如果用户在两个不同的服务器(不同的连接)会怎样?
    • 您需要在两个数据库之间建立一个数据库链接,当然您必须在 SQL 中的适当位置指定该链接。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-06
    • 2011-11-28
    • 1970-01-01
    • 2011-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多