关于修复数据的问题(案例1)

Posted xls0517

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于修复数据的问题(案例1)相关的知识,希望对你有一定的参考价值。

1、背景:

  客户要求更改员工编号,使其具有某一 特定规则,此编号类似于人员的ID,可能被几十张表引用

2、思路:

  先找到关联此字段的具体表以及具体字段,逐一排查确定最终sql语句,写出逻辑规则,采用程序输出的方式输出修复语句

3、具体实现:

  

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.log4j.Logger;

import eman.spring.BaseJdbcDao;
import eman.spring.jdbc.BaseJdbcTemplate;

public class UpdateEManHumanIDSql extends BaseJdbcDao{
private BaseJdbcTemplate jdbc = this.getJdbcTemplate();
private static Logger log4j = Logger.getRootLogger();


/**
* 程序入口
* @author
* @date 2018年8月31日
* @param type
*/
public static void main(String[] args) {
  new UpdateEManHumanIDSql().comprehensiveCallMethod("11");//测试
}


/**
* 方法调用逻辑
* @author
* @date 2018年8月31日
* @param type
*/
public void comprehensiveCallMethod(String type){
  //1、获取Human表中的所有humanID
  List<String> humanList = this.getHumanList();
  //2、将humanID按8位的规则进行拼接,得到键为原humanID,值为新humanID的map
  Map<String, String> humanMap = this.getHumanMap(humanList, type);
  //3、获取需要更新的表名以及表中字段,键为表名,值为涉及字段的list集合
  Map<String, List<String>> tableMap = this.getTableMap();
  //4、执行update语句
  this.mainLogicMethod(tableMap, humanList, humanMap);
}

/**
* 获取humanID集合
* @author
* @date 2018年8月31日
* @return List<String>
*/
private List<String> getHumanList(){
  String sql = "SELECT humanID FROM Human WHERE humanID<>‘admin‘";
  return jdbc.eManForList(sql, String.class);
}

/**
* 
* 获取原来的humanID并根据公司编号拼接新的的humanID,以map的形式返回
* @author
* @date 2018年8月31日
* @param humanIDList - humanID集合
* @param type 
* @return Map<String,String>
* 键 - 原humanID, 值 - 新的humanID
*/
private Map<String, String> getHumanMap(List<String> humanIDList,String type){ 
HashMap<String, String> humanMap = new HashMap<String, String>();
  if (humanIDList == null || humanIDList.isEmpty()) {
    return null;
  }

  String newHumanID = "";
  for (String humanID : humanIDList) {
  newHumanID = humanID;
  if (newHumanID.toUpperCase().contains("KT")) {
    newHumanID = newHumanID.substring(2, newHumanID.length());
  }
  if (newHumanID.length() == 4) {
    humanMap.put(humanID, type + "00" + newHumanID); 
    } else if (newHumanID.length() == 5){
      humanMap.put(humanID, type + "0" + newHumanID); 
    } else if (newHumanID.length() == 6){
      humanMap.put(humanID, type + newHumanID); 
    } else if (newHumanID.length() == 8){
      humanMap.put(humanID, newHumanID); 
    }
  }
  return humanMap;
}

/**
* 获取跟humanID有关的表以及对应的列
* @author 
* @date 2018年8月31日
* @return Map<String,String>
* 键 - 表名, 值 - 字段名的list集合
*/
private Map<String, List<String>> getTableMap(){
  String sql = "SELECT columns.TABLE_NAME,columns.COLUMN_NAME "
    + " FROM information_schema.columns "
    + " WHERE DATA_TYPE LIKE ‘%char‘ "
    + " AND (COLUMN_NAME LIKE ‘%human%‘ "
    + " OR COLUMN_NAME LIKE ‘%oper%‘ "
    + " OR COLUMN_NAME LIKE ‘%person%‘ "
    + " OR COLUMN_NAME LIKE ‘%executor%‘ "
    + " OR COLUMN_NAME LIKE ‘%loginID%‘"
    + " OR COLUMN_NAME LIKE ‘%projectAdderID%‘ "
    + " OR COLUMN_NAME LIKE ‘%man%‘) "
    + " OR COLUMN_NAME LIKE ‘%designer%‘) "
    + " OR COLUMN_NAME LIKE ‘%employeeID%‘) "
    + " OR COLUMN_NAME LIKE ‘%checkID%‘) "
    + " AND COLUMN_NAME NOT LIKE ‘%operation%‘ "
    + " AND COLUMN_NAME NOT IN (‘Wit_TreatManner‘,‘humanMonitorID‘,‘humanMonitorLengthID‘,‘humanSort‘"
    + ",‘manageState‘,‘HumanName‘,‘manufactureClassID‘,‘directoryProperties‘,‘demandFrom‘) "
    + " AND TABLE_NAME NOT LIKE ‘v_%‘"
    + " AND TABLE_NAME NOT LIKE ‘%View%‘";
  return jdbc.eManForMapList(sql, null, String.class, String.class);
}

/**
* 主逻辑
* @author
* @date 2018年8月31日
* @param tableMap - 涉及的表以及字段的集合
* @param humanList - humanID集合
* @param humanMap - 键-原来的humanID,值-新的humanID
*/
private void mainLogicMethod(Map<String, List<String>> tableMap, List<String> humanList
, Map<String, String> humanMap){
  if (tableMap == null || tableMap.isEmpty()) {//涉及表为空直接返回
    return;
  }

  Set<Entry<String, List<String>>> entrySet = tableMap.entrySet();
  String key = "";//tableMap的键
  List<String> value = new ArrayList<String>();//tableMap的值
  List<String> list = new ArrayList<String>();//指定表及指定列需要更新的值集合
  int i = 1;//用于调试输出更新的第几张表
  try {
    this.beginTransaction();
    for (Entry<String, List<String>> entry : entrySet) {
      key = entry.getKey();
      value = entry.getValue();
      if (value == null) {
        continue;
      }
    System.out.println("--更新第"+ i +"张表:" + key);//调试信息,实际可忽略!
    for (String column : value) {
      if ("BOM".equals(key)) {
        System.out.println();
      }
      list = this.getRelationHumanID(key, column);//获取涉及字段的值不为空的list集合
      if (list == null || list.size() == 0) {//为空直接跳过
        System.out.println(" --第"+ i +"张表" + key + "的列" + column + "无需要更新记录!");//调试信息,实际可忽略!
        continue;
      }
      System.out.println("--更新列:" + column);//调试信息,实际可忽略!
      for (String str : list) {//执行更新
        if (humanMap.containsKey(str)) {
          this.updateRelationHumanID(key, column,str,humanMap.get(str));
        }
      }
    }
    i++;
  }

  this.commit();
  } catch (Exception e) {
    log4j.warn("更新失败!", e);
    e.printStackTrace();
  }
}

/**
* 获取当前表中对应字段需要更新的值
* @author
* @date 2018年8月31日
* @param tableName
* @param columnName
* @return List<String> - 需要更新的值集合
*/
private List<String> getRelationHumanID(String tableName, String columnName){
  String sql = "SELECT DISTINCT " + columnName + " FROM " + tableName + 
    " WHERE " + columnName + " IS NOT NULL AND " + columnName + "<>‘‘";
  return jdbc.eManForList(sql, String.class);
}

/**
* 获取更新语句
* @author
* @date 2018年8月31日
* @param tableName - 表名
* @param columnName - 字段名
* @param humanID - 原humanID
* @param newHumanID - 新的humanID
*/
private void updateRelationHumanID(String tableName, String columnName
, String humanID, String newHumanID){
  String sql = "UPDATE " + tableName + " SET " + columnName + " = ‘" + newHumanID 
    + "‘ WHERE " + columnName + " = ‘" + humanID + "‘";
  this.jdbc.update(sql);
  System.out.println(sql);
}

}

 

3.2、禁用外键和触发器

-- 禁用所有的外键约束
DECLARE @sql1 NVARCHAR (1000)
DECLARE @tabname VARCHAR (50)
DECLARE @tabfkn VARCHAR (100)
DECLARE tabs CURSOR FOR SELECT b.name tabname , a.name tabfk FROM sysobjects a , sysobjects b WHERE a.xtype = ‘f‘ AND a.parent_obj = b.id

OPEN tabs
FETCH next FROM tabs INTO @tabname, @tabfkn

WHILE @@FETCH_STATUS = 0
BEGIN
SET @sql1 = ‘ALTER TABLE [‘ + @tabname + ‘] NOCHECK CONSTRAINT ‘+ @tabfkn +‘;‘;
-- PRINT @sql1;
EXEC sp_executesql @sql1;
FETCH next FROM tabs INTO @tabname, @tabfkn
END
CLOSE tabs
DEALLOCATE tabs
GO

-- 禁用所有的触发器约束
DECLARE @sql1 NVARCHAR (1000)
DECLARE @tabname VARCHAR (50)
DECLARE @tabfkn VARCHAR (100)
DECLARE tabs CURSOR FOR SELECT b.name tabname , a.name tabfk FROM sysobjects a , sysobjects b WHERE a.xtype = ‘TR‘ AND a.parent_obj = b.id

OPEN tabs
FETCH next FROM tabs INTO @tabname, @tabfkn

WHILE @@FETCH_STATUS = 0
BEGIN
SET @sql1 = ‘ALTER TABLE [‘ + @tabname + ‘] DISABLE TRIGGER ‘+ @tabfkn +‘;‘;
-- PRINT @sql1;
EXEC sp_executesql @sql1;
FETCH next FROM tabs INTO @tabname, @tabfkn
END
CLOSE tabs
DEALLOCATE tabs
GO

3.3、启用外键和触发器

-- 启用所有的触发器约束
DECLARE @sql1 NVARCHAR (1000)
DECLARE @tabname VARCHAR (50)
DECLARE @tabfkn VARCHAR (100)
DECLARE tabs CURSOR FOR SELECT b.name tabname , a.name tabfk FROM sysobjects a , sysobjects b WHERE a.xtype = ‘TR‘ AND a.parent_obj = b.id

OPEN tabs
FETCH next FROM tabs INTO @tabname, @tabfkn

WHILE @@FETCH_STATUS = 0
BEGIN
SET @sql1 = ‘ALTER TABLE [‘ + @tabname + ‘] ENABLE TRIGGER ‘+ @tabfkn +‘;‘;
-- PRINT @sql1;
EXEC sp_executesql @sql1;
FETCH next FROM tabs INTO @tabname, @tabfkn
END
CLOSE tabs
DEALLOCATE tabs
GO

-- 启用所有的外键约束
DECLARE @sql1 NVARCHAR (1000)
DECLARE @tabname VARCHAR (50)
DECLARE @tabfkn VARCHAR (100)
DECLARE tabs CURSOR FOR SELECT b.name tabname , a.name tabfk FROM sysobjects a , sysobjects b WHERE a.xtype = ‘f‘ AND a.parent_obj = b.id

OPEN tabs
FETCH next FROM tabs INTO @tabname, @tabfkn

WHILE @@FETCH_STATUS = 0
BEGIN
SET @sql1 = ‘ALTER TABLE [‘ + @tabname + ‘] CHECK CONSTRAINT ‘+ @tabfkn +‘;‘;
-- PRINT @sql1;
EXEC sp_executesql @sql1;
FETCH next FROM tabs INTO @tabname, @tabfkn
END
CLOSE tabs
DEALLOCATE tabs
GO

 

























































以上是关于关于修复数据的问题(案例1)的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server一致性错误修复案例总结

如何修复空白片段?

如何修复重叠的片段

SQL Server一致性错误修复案例总结

Express实战 - 应用案例- realworld-API - 路由设计 - mongoose - 数据验证 - 密码加密 - 登录接口 - 身份认证 - token - 增删改查API(代码片段

记一次血淋淋的MySQL崩溃修复案例