<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    peacess

    統計

    留言簿(14)

    積分與排名

    閱讀排行榜

    評論排行榜

    清空數據庫數據(表)的一個解決方案


    ???? 在做數據庫開發中,經常都要清空(delete)數據或刪除(drop)所有的表。然而,外鍵的存在,給這個工作帶來了很大的不便。這里用jdbc寫一個通用的類,產生出清空或刪除表的順序。
    以下代碼在mysql與oracle下面運行正常

    (在同行的建議下作了一些改進,又增加了一些功能,見類注釋)
    代碼:
    package createData.tryDemo;

    import java.sql.Connection;
    import java.sql.DatabaseMetaData;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;

    /**
    ?* 外鍵工具
    ?* 1,返回清空(刪除)數據庫表的先后順序
    ?* 2,找出數據庫中的外鍵環
    ?* 3,找出數據庫中的對同一個表的重復外鍵關聯
    ?*
    ?* 注:外鍵環(不知道在數據庫中,對此情況有沒有別的命名)
    ?*? 情況1,外鍵表是自己 (自外鍵環、小外鍵環、單外鍵環)
    ?*? 情況2,aTable的外鍵表是bTable,而bTable的外鍵表又是aTable(雙外鍵環)
    ?*? 情況3,就是多個表之間形成的外鍵環(多外鍵環)
    ?* @author wpeace
    ?*
    ?*/
    public class ExportedKeysTools
    {
    ??? public static void main(String[] args)
    ??? {
    ??????? //得到一個數據庫的連接,這里就不細說了
    ??????? Connection connection = null;
    ???????
    ??????? List<String> tables = ExportedKeysTools.getDeleteOrder(connection);
    ???????
    ??????? System.out.print(tables);
    ??????? //清空數據,以oracle為例
    ??????? StringBuilder scrip = new StringBuilder();
    ??????? for(String it : tables)
    ??????? {
    ??????????? scrip.append(String.format("delete from %s;\r\n", it));
    ??????? }
    ??????? System.out.print(scrip);
    ??????? //刪除所有表,以oracle為例
    ???????
    ??????? for(String it : tables)
    ??????? {
    ??????????? scrip.append(String.format("drop table %s;\r\n", it));
    ??????? }
    ??????? System.out.print(scrip);
    ???????
    ??????? //提示關閉連接!!!

    ??? }
    ??? public static List<String> getDeleteOrder(Connection connection)
    ??? {
    ??????? String userName = null;
    ??????? try
    ??????? {
    ??????????? userName = connection.getMetaData().getUserName();
    ??????? }
    ??????? catch (SQLException e)
    ??????? {
    ??????????? e.printStackTrace();
    ??????? }
    ??????? return ExportedKeysTools.getDeleteOrder(connection, userName);
    ??? }
    ??? /**
    ???? * 返回清空(刪除)數據庫表的先后順序
    ???? * @param connection jdbc連接
    ???? * @param userName 如果為null的話,在oracle數據庫下面是所有的用戶的所有表。
    ???? * 在mysql下是當前用用戶的,這個與數據庫廠商的jdbc驅動有關系
    ???? * @return 返回清空(刪除)數據庫表的先后順序
    ???? */
    ??? public static List<String> getDeleteOrder(Connection connection,String userName)
    ??? {
    ??????? ResultSet reTables = null;
    ??????? ResultSet refk = null;
    ??????? try
    ??????? {
    ??????????? DatabaseMetaData dm = connection.getMetaData();
    ??????????? //如果是oracle數據庫的話,清空閃回表
    ??????????? if(dm.getDatabaseProductName().toUpperCase().indexOf("ORACLE")>=0)
    ??????????? {
    ??????????????? Statement state = connection.createStatement();
    ??????????????? state.execute("PURGE RECYCLEBIN");
    ??????????????? state.close();
    ??????????? }
    ??????????? //取得表
    ??????????? reTables = dm.getTables(null, userName, null, new String[]{"TABLE","VIEW"});
    ??????????? List<TableMeta> tableMetaList = new ArrayList<TableMeta>();
    ??????????? while(reTables.next())
    ??????????? {
    ??????????????? String tableName = reTables.getString("TABLE_NAME").trim();
    ??????????????? if(tableName == null || tableName.length()<1)
    ??????????????? {
    ??????????????????? continue;
    ??????????????? }
    ??????????????? TableMeta tem = new TableMeta(tableName);
    ??????????????? tableMetaList.add(tem);
    ??????????????? //取得外鍵表
    ??????????????? refk = dm.getExportedKeys(null, userName, tableName);
    ??????????????? while(refk.next())
    ??????????????? {
    ??????????????????? String fkTableName = refk.getString("FKTABLE_NAME").trim();
    ??????????????????? if(fkTableName == null || fkTableName.length() < 1 ||
    ??????????????????????????? fkTableName.equals(tableName)) //去掉主外鍵是自己的小環
    ??????????????????? {
    ??????????????????????? continue;
    ??????????????????? }
    ??????????????????? tem.addFK(fkTableName);
    ??????????????? }
    ??????????????? if(refk != null)refk.close();
    ??????????? }
    ???????????
    ??????????? Iterator<TableMeta> iterator = tableMetaList.iterator();
    ??????????? TableMeta tableMeta = iterator.next();
    ??????????? List<String> deleteOrder = new ArrayList<String>();
    ??????????? int counts = tableMetaList.size();
    ??????????? for(;true;)
    ??????????? {
    ??????????????? //沒有外鍵了
    ??????????????? if(!tableMeta.isFKTable())
    ??????????????? {
    ??????????????????? iterator.remove();
    ??????????????????? deleteOrder.add(tableMeta.tableName);
    ???????????????????
    ??????????????????? //清除表所使用的所有外鍵表
    ??????????????????? for(TableMeta it : tableMetaList)
    ??????????????????? {
    ??????????????????????? it.deleteFK(tableMeta.tableName);
    ??????????????????? }
    ??????????????? }

    ??????????????? if(!iterator.hasNext())
    ??????????????? {
    ??????????????????? //一次循環完成后,如果tableMeta的長度(也不為零)沒有減少,
    ??????????????????? //那么說明在tableMeta中的表之間有循環外鍵關聯的“環”,要退出整個循環
    ??????????????????? //不然此處就會有一個死循環,此時在tableMeta中的表的設計也許是有問題的
    ??????????????????? //如果要分析
    ??????????????????? if(tableMetaList.size() == counts || tableMetaList.size() < 1)
    ??????????????????? {
    ??????????????????????? break;
    ??????????????????? }
    ??????????????????? iterator = tableMetaList.iterator();
    ??????????????? }
    ??????????????? tableMeta = iterator.next();
    ??????????? }
    ?????????? return deleteOrder;
    ??????? }
    ??????? catch (SQLException e)
    ??????? {
    ??????????? if(refk != null)
    ??????????????? try
    ??????????????? {
    ??????????????????? refk.close();
    ??????????????? }
    ??????????????? catch (SQLException e1)
    ??????????????? {
    ??????????????????? e1.printStackTrace();
    ??????????????? }
    ??????????? if(reTables != null)
    ??????????????? try
    ??????????????? {
    ??????????????????? reTables.close();
    ??????????????? }
    ??????????????? catch (SQLException e1)
    ??????????????? {
    ??????????????????? e1.printStackTrace();
    ??????????????? }
    ??????????? e.printStackTrace();
    ??????? }
    ??????? return null;
    ??? }
    ??? /**
    ???? * 返回外鍵環
    ???? * @param connection 連接
    ???? * @param userName 用戶名,可以為空
    ???? * @return 返回外鍵環
    ???? */
    ??? public static List<String> getExportedKeysLoop(Connection connection,String userName)
    ??? {
    ??????? ResultSet reTables = null;
    ??????? ResultSet refk = null;
    ??????? try
    ??????? {
    ??????????? DatabaseMetaData dm = connection.getMetaData();
    ??????????? //如果是oracle數據庫的話,清空閃回表
    ??????????? if(dm.getDatabaseProductName().toUpperCase().indexOf("ORACLE")>=0)
    ??????????? {
    ??????????????? Statement state = connection.createStatement();
    ??????????????? state.execute("PURGE RECYCLEBIN");
    ??????????????? state.close();
    ??????????? }
    ??????????? //取得表
    ??????????? reTables = dm.getTables(null, userName, null, new String[]{"TABLE","VIEW"});
    ??????????? List<TableMeta> tableMetaList = new ArrayList<TableMeta>();
    ??????????? while(reTables.next())
    ??????????? {
    ??????????????? String tableName = reTables.getString("TABLE_NAME").trim();
    ??????????????? if(tableName == null || tableName.length()<1)
    ??????????????? {
    ??????????????????? continue;
    ??????????????? }
    ??????????????? TableMeta tem = new TableMeta(tableName);
    ??????????????? tableMetaList.add(tem);
    ??????????????? //取得外鍵表
    ??????????????? refk = dm.getExportedKeys(null, userName, tableName);
    ??????????????? while(refk.next())
    ??????????????? {
    ??????????????????? String fkTableName = refk.getString("FKTABLE_NAME").trim();
    ??????????????????? if(fkTableName == null || fkTableName.length() < 1 ||
    ??????????????????????????? fkTableName.equals(tableName)) //去掉主外鍵是自己的小環
    ??????????????????? {
    ??????????????????????? continue;
    ??????????????????? }
    ??????????????????? tem.addFK(fkTableName);
    ??????????????? }
    ??????????????? if(refk != null)refk.close();
    ??????????? }
    ???????????
    ??????????? Iterator<TableMeta> iterator = tableMetaList.iterator();
    ??????????? TableMeta tableMeta = iterator.next();
    ??????????? List<String> exportedKeysLoop = new ArrayList<String>();
    ??????????? int counts = tableMetaList.size();
    ??????????? for(;true;)
    ??????????? {
    ??????????????? //沒有外鍵了
    ??????????????? if(!tableMeta.isFKTable())
    ??????????????? {
    ??????????????????? iterator.remove();???????????????????
    ??????????????????? //清除表所使用的所有外鍵表
    ??????????????????? for(TableMeta it : tableMetaList)
    ??????????????????? {
    ??????????????????????? it.deleteFK(tableMeta.tableName);
    ??????????????????? }
    ??????????????? }

    ??????????????? if(!iterator.hasNext())
    ??????????????? {
    ??????????????????? //一次循環完成后,如果tableMeta的長度(也不為零)沒有減少,
    ??????????????????? //那么說明在tableMeta中的表之間有循環外鍵關聯的“環”,要退出整個循環
    ??????????????????? //不然此處就會有一個死循環,此時在tableMeta中的表的設計也許是有問題的
    ??????????????????? //如果要分析
    ??????????????????? if(tableMetaList.size() == counts || tableMetaList.size() < 1)
    ??????????????????? {
    ??????????????????????? for(TableMeta it : tableMetaList)
    ??????????????????????? {
    ??????????????????????????? exportedKeysLoop.add(it.tableName);
    ??????????????????????? }
    ??????????????????????? break;
    ??????????????????? }
    ??????????????????? iterator = tableMetaList.iterator();
    ??????????????? }
    ??????????????? tableMeta = iterator.next();
    ??????????? }
    ?????????? return exportedKeysLoop;
    ??????? }
    ??????? catch (SQLException e)
    ??????? {
    ??????????? if(refk != null)
    ??????????????? try
    ??????????????? {
    ??????????????????? refk.close();
    ??????????????? }
    ??????????????? catch (SQLException e1)
    ??????????????? {
    ??????????????????? e1.printStackTrace();
    ??????????????? }
    ??????????? if(reTables != null)
    ??????????????? try
    ??????????????? {
    ??????????????????? reTables.close();
    ??????????????? }
    ??????????????? catch (SQLException e1)
    ??????????????? {
    ??????????????????? e1.printStackTrace();
    ??????????????? }
    ??????????? e.printStackTrace();
    ??????? }
    ??????? return null;
    ??? }
    ??? /**
    ???? * 有重復外鍵的表
    ???? * @param connection 連接
    ???? * @param userName 用戶名,可以為空
    ???? * @return 有重復外鍵的表
    ???? */
    ??? public static List<String> getRepeatExportedKeys(Connection connection,String userName)
    ??? {
    ??????? ResultSet reTables = null;
    ??????? ResultSet refk = null;
    ??????? try
    ??????? {
    ??????????? DatabaseMetaData dm = connection.getMetaData();
    ??????????? //如果是oracle數據庫的話,清空閃回表
    ??????????? if(dm.getDatabaseProductName().toUpperCase().indexOf("ORACLE")>=0)
    ??????????? {
    ??????????????? Statement state = connection.createStatement();
    ??????????????? state.execute("PURGE RECYCLEBIN");
    ??????????????? state.close();
    ??????????? }
    ???????????
    ??????????? List<String> repeatExportedKeys = new ArrayList<String>();
    ??????????? //取得表
    ??????????? reTables = dm.getTables(null, userName, null, new String[]{"TABLE","VIEW"});
    ??????????? while(reTables.next())
    ??????????? {
    ??????????????? String tableName = reTables.getString("TABLE_NAME").trim();
    ??????????????? if(tableName == null || tableName.length()<1)
    ??????????????? {
    ??????????????????? continue;
    ??????????????? }
    ??????????????? TableMeta tem = new TableMeta(tableName);
    ??????????????? //取得外鍵表
    ??????????????? refk = dm.getExportedKeys(null, userName, tableName);
    ??????????????? while(refk.next())
    ??????????????? {
    ??????????????????? String fkTableName = refk.getString("FKTABLE_NAME").trim();
    ??????????????????? if(fkTableName == null || fkTableName.length() < 1)
    ??????????????????? {
    ??????????????????????? continue;
    ??????????????????? }
    ??????????????????? if(tem.findFK(fkTableName))
    ??????????????????? {
    ??????????????????????? repeatExportedKeys.add(tem.tableName);
    ??????????????????????? break;
    ??????????????????? }
    ???????????????? }
    ??????????????? if(refk != null)refk.close();
    ??????????? }
    ?????????? return repeatExportedKeys;
    ??????? }
    ??????? catch (SQLException e)
    ??????? {
    ??????????? if(refk != null)
    ??????????????? try
    ??????????????? {
    ??????????????????? refk.close();
    ??????????????? }
    ??????????????? catch (SQLException e1)
    ??????????????? {
    ??????????????????? e1.printStackTrace();
    ??????????????? }
    ??????????? if(reTables != null)
    ??????????????? try
    ??????????????? {
    ??????????????????? reTables.close();
    ??????????????? }
    ??????????????? catch (SQLException e1)
    ??????????????? {
    ??????????????????? e1.printStackTrace();
    ??????????????? }
    ??????????? e.printStackTrace();
    ??????? }
    ??????? return null;
    ??? }
    ??? public static class TableMeta{
    ??????? //表名
    ??????? public String tableName;
    ??????? //外鍵表
    ??????? private List<String> fkTable = new ArrayList<String>(1);
    ??????? public TableMeta(String table)
    ??????? {
    ??????????? this.tableName = table;
    ??????? }
    ??????? public boolean findFK(String table)
    ??????? {
    ??????????? return fkTable.contains(table);
    ??????? }
    ??????? public void deleteFK(String table)
    ??????? {
    ??????????? fkTable.remove(table);
    ??????? }
    ??????? //是否存在外鍵表
    ??????? public boolean isFKTable()
    ??????? {
    ??????????? return fkTable.size() > 0;
    ??????? }
    ??????? public void addFK(String table)
    ??????? {
    ??????????? //重名處理
    ??????????? if(!findFK(table))
    ??????????? {
    ??????????????? fkTable.add(table);
    ??????????? }
    ??????? }
    ??? }

    }






    posted on 2006-11-09 17:18 中東 閱讀(10149) 評論(10)  編輯  收藏 所屬分類: 數據庫設計篇

    評論

    # re: 清空數據庫數據(表)的一個解決方案 2006-11-09 17:39 馬嘉楠

    問一下
    在哪里關閉連接(Connection)?

    方法中聲明的ResultSet也沒有關閉
    好像有點不妥吧

    不需要關閉么?

      回復  更多評論   

    # re: 清空數據庫數據(表)的一個解決方案 2006-11-09 21:11 中東

    記錄集是應該關閉的,數據庫連接就不用了,是從從面從入的  回復  更多評論   

    # 不需要關閉么? 2006-11-09 21:22 中東

    謝謝你的提示,我再修改了一上,減少它的錯誤  回復  更多評論   

    # re: 清空數據庫數據(表)的一個解決方案 2006-11-09 21:38 海邊沫沫

    標準SQL語法:
    FOREIGN KEY [id] (index_col_name, ...)
    REFERENCES tbl_name (index_col_name, ...)
    [ON DELETE {RESTRICT | CASCADE | SET NULL | NO ACTION}]
    [ON UPDATE {RESTRICT | CASCADE | SET NULL | NO ACTION}]
    其中:
    CASCADE: 從父表刪除或更新且自動刪除或更新子表中匹配的行。ON DELETE CASCADE和ON UPDATE CASCADE都可用。在兩個表之間,你不應定義若干在父表或子表中的同一列采取動作的ON UPDATE CASCADE子句。

    SET NULL: 從父表刪除或更新行,并設置子表中的外鍵列為NULL。如果外鍵列沒有指定NOT NULL限定詞,這就是唯一合法的。ON DELETE SET NULL和ON UPDATE SET NULL子句被支持。

    NO ACTION: 在ANSI SQL-92標準中,NO ACTION意味這不采取動作,就是如果有一個相關的外鍵值在被參考的表里,刪除或更新主要鍵值的企圖不被允許進行(Gruber, 掌握SQL, 2000:181)。 InnoDB拒絕對父表的刪除或更新操作。

    RESTRICT: 拒絕對父表的刪除或更新操作。NO ACTION和RESTRICT都一樣,刪除ON DELETE或ON UPDATE子句。(一些數據庫系統有延期檢查,并且NO ACTION是一個延期檢查。在MySQL中,外鍵約束是被立即檢查的,所以NO ACTION和RESTRICT是同樣的)。

    一句話頂你幾百行代碼,呵呵。  回復  更多評論   

    # re: 清空數據庫數據(表)的一個解決方案 2006-11-09 22:11 中東

    讓外鍵約束失效,再進行刪除,這種方法很好。
    我用的是軟件方法,不破壞原來數據庫的結構,各有優點啊!!!!!  回復  更多評論   

    # re: 清空數據庫數據(表)的一個解決方案 2006-11-09 23:22 stoneshao[匿名]

    可以試一下,dbunit  回復  更多評論   

    # re: 清空數據庫數據(表)的一個解決方案 2006-11-10 11:06

    我看你的封裝就很失敗。

    truncate table table1

    快速。不會產生回滾段。又能釋放表空間。。  回復  更多評論   

    # re: 清空數據庫數據(表)的一個解決方案 2006-11-10 11:33 壞男孩

    踩個腳印;truncate table 是oracle的吧,這兒是通用的吧  回復  更多評論   

    # re: 清空數據庫數據(表)的一個解決方案 2006-11-10 11:43 jeffjie

    DBUnit是解決不了這個問題的。
    這也是使用dbunit總不順手的原因。
    后來我自已也寫了個類似的程序。
    不過有個問題問問樓主:
    如果一個表的主鍵外鍵都是自已,你的程序能處理這個問題嗎?可以避免死循環?  回復  更多評論   

    # re: 清空數據庫數據(表)的一個解決方案 2006-11-13 11:12 peace

    @jeffjie
    這位提的很好,這個類有一個問題,就是表間的外鍵構成一個“環”(主外鍵自己的也是一個小環)時,程序會出現死循環。這個問題我再改進一下,看能不能找出解決方法,主外鍵自己的小環應該好辦,主要是幾個表之間的環,就不好處理了,不過,一般設計數據庫應該不會有這樣的情況,因為幾個表之間構成環,也就是相互依懶,插入數據都插不進去?  回復  更多評論   

    主站蜘蛛池模板: 亚洲狠狠综合久久| 男人扒开添女人下部免费视频| 最近最新的免费中文字幕| 亚洲av纯肉无码精品动漫| 亚洲一区二区三区自拍公司| 2020因为爱你带字幕免费观看全集 | 亚洲欧洲日韩在线电影| 成在线人永久免费视频播放| a级毛片免费播放| 亚洲国产综合精品中文第一| 国产亚洲情侣一区二区无| 日韩精品成人无码专区免费| 中国黄色免费网站| 亚洲熟妇少妇任你躁在线观看| 亚洲中文字幕无码一区| 成人一a毛片免费视频| 女同免费毛片在线播放| 欧美激情综合亚洲一二区| 亚洲一区二区三区首页| 亚洲精品麻豆av| 成人男女网18免费视频| 午夜视频在线免费观看| av电影在线免费看| 亚洲精品无码成人片久久不卡 | 免费网站看v片在线香蕉| 久草免费福利资源站| 男女男精品网站免费观看| 亚洲专区中文字幕| 亚洲s色大片在线观看| www.亚洲精品.com| 国内大片在线免费看| 99视频全部免费精品全部四虎| 久久免费香蕉视频| 美女黄频a美女大全免费皮| 亚洲一级免费视频| 精品亚洲aⅴ在线观看| 亚洲熟妇中文字幕五十中出| 免费A级毛片在线播放不收费| A在线观看免费网站大全| 一级毛片在线免费看| 99re8这里有精品热视频免费|