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

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

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

    peacess

    統(tǒng)計

    留言簿(14)

    積分與排名

    閱讀排行榜

    評論排行榜

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


    ???? 在做數(shù)據(jù)庫開發(fā)中,經(jīng)常都要清空(delete)數(shù)據(jù)或刪除(drop)所有的表。然而,外鍵的存在,給這個工作帶來了很大的不便。這里用jdbc寫一個通用的類,產(chǎn)生出清空或刪除表的順序。
    以下代碼在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,返回清空(刪除)數(shù)據(jù)庫表的先后順序
    ?* 2,找出數(shù)據(jù)庫中的外鍵環(huán)
    ?* 3,找出數(shù)據(jù)庫中的對同一個表的重復(fù)外鍵關(guān)聯(lián)
    ?*
    ?* 注:外鍵環(huán)(不知道在數(shù)據(jù)庫中,對此情況有沒有別的命名)
    ?*? 情況1,外鍵表是自己 (自外鍵環(huán)、小外鍵環(huán)、單外鍵環(huán))
    ?*? 情況2,aTable的外鍵表是bTable,而bTable的外鍵表又是aTable(雙外鍵環(huán))
    ?*? 情況3,就是多個表之間形成的外鍵環(huán)(多外鍵環(huán))
    ?* @author wpeace
    ?*
    ?*/
    public class ExportedKeysTools
    {
    ??? public static void main(String[] args)
    ??? {
    ??????? //得到一個數(shù)據(jù)庫的連接,這里就不細說了
    ??????? Connection connection = null;
    ???????
    ??????? List<String> tables = ExportedKeysTools.getDeleteOrder(connection);
    ???????
    ??????? System.out.print(tables);
    ??????? //清空數(shù)據(jù),以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);
    ???????
    ??????? //提示關(guān)閉連接?。?!

    ??? }
    ??? 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);
    ??? }
    ??? /**
    ???? * 返回清空(刪除)數(shù)據(jù)庫表的先后順序
    ???? * @param connection jdbc連接
    ???? * @param userName 如果為null的話,在oracle數(shù)據(jù)庫下面是所有的用戶的所有表。
    ???? * 在mysql下是當前用用戶的,這個與數(shù)據(jù)庫廠商的jdbc驅(qū)動有關(guān)系
    ???? * @return 返回清空(刪除)數(shù)據(jù)庫表的先后順序
    ???? */
    ??? public static List<String> getDeleteOrder(Connection connection,String userName)
    ??? {
    ??????? ResultSet reTables = null;
    ??????? ResultSet refk = null;
    ??????? try
    ??????? {
    ??????????? DatabaseMetaData dm = connection.getMetaData();
    ??????????? //如果是oracle數(shù)據(jù)庫的話,清空閃回表
    ??????????? 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)) //去掉主外鍵是自己的小環(huán)
    ??????????????????? {
    ??????????????????????? 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())
    ??????????????? {
    ??????????????????? //一次循環(huán)完成后,如果tableMeta的長度(也不為零)沒有減少,
    ??????????????????? //那么說明在tableMeta中的表之間有循環(huán)外鍵關(guān)聯(lián)的“環(huán)”,要退出整個循環(huán)
    ??????????????????? //不然此處就會有一個死循環(huán),此時在tableMeta中的表的設(shè)計也許是有問題的
    ??????????????????? //如果要分析
    ??????????????????? 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;
    ??? }
    ??? /**
    ???? * 返回外鍵環(huán)
    ???? * @param connection 連接
    ???? * @param userName 用戶名,可以為空
    ???? * @return 返回外鍵環(huán)
    ???? */
    ??? public static List<String> getExportedKeysLoop(Connection connection,String userName)
    ??? {
    ??????? ResultSet reTables = null;
    ??????? ResultSet refk = null;
    ??????? try
    ??????? {
    ??????????? DatabaseMetaData dm = connection.getMetaData();
    ??????????? //如果是oracle數(shù)據(jù)庫的話,清空閃回表
    ??????????? 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)) //去掉主外鍵是自己的小環(huán)
    ??????????????????? {
    ??????????????????????? 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())
    ??????????????? {
    ??????????????????? //一次循環(huán)完成后,如果tableMeta的長度(也不為零)沒有減少,
    ??????????????????? //那么說明在tableMeta中的表之間有循環(huán)外鍵關(guān)聯(lián)的“環(huán)”,要退出整個循環(huán)
    ??????????????????? //不然此處就會有一個死循環(huán),此時在tableMeta中的表的設(shè)計也許是有問題的
    ??????????????????? //如果要分析
    ??????????????????? 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;
    ??? }
    ??? /**
    ???? * 有重復(fù)外鍵的表
    ???? * @param connection 連接
    ???? * @param userName 用戶名,可以為空
    ???? * @return 有重復(fù)外鍵的表
    ???? */
    ??? public static List<String> getRepeatExportedKeys(Connection connection,String userName)
    ??? {
    ??????? ResultSet reTables = null;
    ??????? ResultSet refk = null;
    ??????? try
    ??????? {
    ??????????? DatabaseMetaData dm = connection.getMetaData();
    ??????????? //如果是oracle數(shù)據(jù)庫的話,清空閃回表
    ??????????? 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 中東 閱讀(10152) 評論(10)  編輯  收藏 所屬分類: 數(shù)據(jù)庫設(shè)計篇

    評論

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

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

    方法中聲明的ResultSet也沒有關(guān)閉
    好像有點不妥吧

    不需要關(guān)閉么?

      回復(fù)  更多評論   

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

    記錄集是應(yīng)該關(guān)閉的,數(shù)據(jù)庫連接就不用了,是從從面從入的  回復(fù)  更多評論   

    # 不需要關(guān)閉么? 2006-11-09 21:22 中東

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

    # re: 清空數(shù)據(jù)庫數(shù)據(jù)(表)的一個解決方案 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都可用。在兩個表之間,你不應(yīng)定義若干在父表或子表中的同一列采取動作的ON UPDATE CASCADE子句。

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

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

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

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

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

    讓外鍵約束失效,再進行刪除,這種方法很好。
    我用的是軟件方法,不破壞原來數(shù)據(jù)庫的結(jié)構(gòu),各有優(yōu)點?。。。。。?nbsp; 回復(fù)  更多評論   

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

    可以試一下,dbunit  回復(fù)  更多評論   

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

    我看你的封裝就很失敗。

    truncate table table1

    快速。不會產(chǎn)生回滾段。又能釋放表空間。。  回復(fù)  更多評論   

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

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

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

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

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

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

    主站蜘蛛池模板: 亚洲自偷自偷在线制服| 一级毛片免费在线播放| 亚洲欧洲无码AV电影在线观看 | 成人免费视频网址| a毛片免费在线观看| 真人无码作爱免费视频| 国产成人亚洲综合一区| 日韩亚洲Av人人夜夜澡人人爽| 亚洲日本一区二区三区在线不卡| 成年女人毛片免费播放人| 1区2区3区产品乱码免费| 在线观看免费无码视频| 欧洲精品码一区二区三区免费看| 亚洲人AV在线无码影院观看| 久久久久亚洲精品天堂| 亚洲精品国精品久久99热一| 亚洲福利精品电影在线观看| 午夜影视在线免费观看| 无码人妻精品一二三区免费| h在线观看视频免费网站| 久久国产精品一区免费下载| 女人隐私秘视频黄www免费| 一级特级女人18毛片免费视频| 亚洲avav天堂av在线网毛片| 伊人久久五月丁香综合中文亚洲| 亚洲高清资源在线观看| 午夜亚洲www湿好大| 亚洲乱码国产乱码精品精| 中文字幕亚洲日韩无线码| 亚洲成AV人在线观看网址| 免费在线观看的黄色网址| 四虎国产精品免费视| 日韩一区二区在线免费观看| 日韩高清在线高清免费| 性xxxx视频播放免费| 午夜视频免费观看| 国产jizzjizz免费视频| 国产免费爽爽视频免费可以看| 国产最新凸凹视频免费| 国产免费AV片无码永久免费| 免费大片在线观看网站|