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