自动剔除所有表,有外键约束的表优先删除
自动删除所有表,有外键约束的表优先删除
很棒!
在数据迁移的过程中,可能涉及到要清除数据库中表数据,大家在做删除操作的过程中经常遇到,想要删除的表往往有很多外键相关联的表,必须将这些有关联的表的数据清空掉以后,才能将需要删除的表数据清空。
如:delete from testXX;报错外键约束 ‘FK_XX_XX’ 这样需要查询是那张表,select * from user_constraints t where lower(t.constraint_name) like 'fk_xx_xx%' 往往这个过程有些复杂,执行删除语句,发现是哪个外键引用,然后找到表,然后清除这个引用表的数据,然后继续以上步骤。。。
基于此类繁琐的操作,要删除的表少了还可以手动测试,最后整理需要顺序删除的语句,但是如果表很多,这个过程就相当繁琐了,所以决定写一个测试类,来解决这个问题,让程序自动运行,自动删除表,遇到有外键约束的表优先删除后,再进行删除需要删除的表。
代码如下:
import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.servlet.UnavailableException; /** * @author Bicashy */ public class TableOperate { static Statement stmt = null; static Connection conn = null; static Map map = new HashMap(); //用来保存已经删除了的表的集合 static Map filterMap = new HashMap(); //用来保存需要过滤的表的集合 static String schema ; /** * 获得数据库链接 * @return */ private static Connection getConnection(){ try { Class.forName( "oracle.jdbc.driver.OracleDriver").newInstance(); //String url= "jdbc:oracle:thin:@10.45.10.177:1521:highway"; String url= "jdbc:oracle:thin:@127.0.0.1:1521:highway"; String user= "sa"; String password= "123456"; schema = user; conn = DriverManager.getConnection(url,user,password); return conn; } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } /** * 获得该用户的所有表,并删除表(除了要过滤的表) */ private static void findDeleteTableSQL(){ if(conn!=null){ try { stmt=conn.createStatement(); String sql = "select * from user_tables"; //找到该链接用户的所有表 ResultSet rs=stmt.executeQuery(sql); while(rs.next()){ String tabName = rs.getString("table_name"); //如果map中包含了表名,说明已经删除过了 //如果filterMap中包含了表名,则不删除 if(!map.containsKey(tabName)&&!filterMap.containsKey(tabName)){ printDeleteTableSQL(tabName); } } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } /** * * 删除表,并将删除表的语句输出到控制台(记录后方便在数据库客户端执行) * @param l * @param tableName * @return */ private static void printDeleteTableSQL(String tableName){ String sql = "DELETE FROM "+tableName.toUpperCase(); try { stmt=conn.createStatement(); stmt.execute(sql); stmt.close(); System.out.println(sql+";"); //将删除语句输出到控制台 map.put(tableName,null); } catch (Exception e) { // TODO Auto-generated catch block String error = e.toString(); String errorStart = "java.sql.SQLException: ORA-02292: 违反完整约束条件 ("+schema.toUpperCase()+"."; int start = errorStart.length(); int end = error.length()-") - 已找到子记录 ".length(); //截取错误信息得到外键约束名称 String fk_constraints = error.substring(start,end); deleteTableNameFromFK(fk_constraints); //删除外键约束表后,就可以将本表删掉 printDeleteTableSQL(tableName); } } /** * 删除通过外键约束找到的有子记录的表 * @param fk_constraints */ private static void deleteTableNameFromFK(String fk_constraints){ String sql = "select table_name from user_constraints where constraint_name='"+fk_constraints+"'"; try { ResultSet rs=stmt.executeQuery(sql); while(rs.next()){ String tabN = rs.getString("table_name"); printDeleteTableSQL(tabN);//递归 } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 初始化需要过滤表的集合(该表如果是别的表的外键关联表也有可能被删除) */ private static void initFilterMap(){ String[] tables = {"ETC_USER","etc_dic_data","MENU"}; for (int j = 0; j < tables.length; j++) { filterMap.put(tables[j].toUpperCase(),null); } } public static void main(String[] args) { getConnection(); //initFilterMap();//初始化不需要删除的表 //删除该用户下所有表(除了需要过滤的),并获得删除语句 //findDeleteTableSQL(); //删除某一个表(有外键约束的表将先删除),并获得删除语句 printDeleteTableSQL("obu_mast"); } }
1 楼
jeans_1312
2011-08-11