有這么一種場景,設(shè)計(jì)好的數(shù)據(jù)模型在有數(shù)據(jù)以后要修改數(shù)據(jù)模型。本文就是針對這個(gè)問題展開的。
              要增加,刪除一列,這根本不是問題,關(guān)鍵是要修改一列。這需要考慮到那些問題呢?
              在java里面有類型轉(zhuǎn)換,轉(zhuǎn)換分為兩種:自然轉(zhuǎn)換和強(qiáng)制轉(zhuǎn)換。自然轉(zhuǎn)換就是把子類型轉(zhuǎn)成父類型,強(qiáng)制轉(zhuǎn)換就是把父類型轉(zhuǎn)成子類型。在數(shù)據(jù)庫里面也一樣,當(dāng)然還要包括長度的截短和加長。強(qiáng)制轉(zhuǎn)換和截短會(huì)造成數(shù)據(jù)的不準(zhǔn)確和異常,本文不考慮這個(gè)情況。
              那么,如何改變數(shù)據(jù)表的列類型呢?通過SQL語句直接操作數(shù)據(jù)庫,當(dāng)然能解決這個(gè)問題,可是,如何有很多張表都要修改呢?那不把人累死了!!!
           
              我就碰到了這么一個(gè)問題,加班加點(diǎn)的,寫成了一個(gè)JAVA小程序,來自動(dòng)實(shí)現(xiàn)我的要求。

              需求:把數(shù)據(jù)庫中字段類型為blob和varchar2(4000)的數(shù)據(jù)表都修改為clob;

              問題解決思路:復(fù)制數(shù)據(jù)表結(jié)構(gòu)和數(shù)據(jù)到一個(gè)臨時(shí)表,先刪除要修改的列,再創(chuàng)建同名不同類型的列,從原始表中查出這一列的數(shù)據(jù),復(fù)制的臨時(shí)表中,刪除原始表,修改臨時(shí)表名為原始表名。

              處理過程日志截圖:


              代碼思路及重要代碼:
              1:獲取系統(tǒng)所有的用戶表:
                       String sql = " select table_name from user_tables " ;
              2:獲取表的主鍵(只考慮單主鍵) 
                       String sql = "  select column_name from user_cons_columns " +
                                  "  where constraint_name = (" +
                                        "  select constraint_name from user_constraints " +
                                            " where table_name = upper('"+tableName+"') " +
                                                "and constraint_type = 'P'" +
                                                    ")" ; 
              3:獲取表中列信息:列名,類型 和長度。
                       String sql = " select column_name,data_type,data_length from user_tab_columns  where table_name =  '"+ tableName+"'" ;   
              4:根據(jù)2和3,判斷要修改的列,組織(主鍵和要修改的列信息)數(shù)據(jù)。
                  代碼片段:

                  List<String[]> :裝有要修改表的表名,主鍵,列信息(列名,類型,長度);List中,第一條數(shù)據(jù)為表名,第二條數(shù)據(jù)為主鍵,其余為要修改的列信息,String[]為變長數(shù)組;
             
          String columnName="";
                  String dataType
          ="";
                  String dataLength
          ="";
                  List
          <String[]> result = new ArrayList<String[]>(3);
                  result.add(
          new String[]{tableName});
                  String primaryKeyName 
          = getPrimaryKey(tableName);
                  
          if(primaryKeyName.equals("")||primaryKeyName==nullreturn null ;
                  result.add(
          new String[]{primaryKeyName});
                      
          try {
                          String sql 
          = " select column_name,data_type,data_length from user_tab_columns  where table_name =  '"+ tableName+"'" ;    
                          ResultSet resultSet 
          = OracleDBUtil.executeQuery(sql);
                          
          while(resultSet.next()){
                              columnName
          =resultSet.getString(1);
                              dataType
          =resultSet.getString(2);
                              dataLength
          =resultSet.getString(3);
                              
          if(dataType.equals("BLOB")){
                                  result.add(
          new String[]{columnName,dataType});
                              }
          else if((dataType.equals("VARCHAR2")&&Integer.parseInt(dataLength) >= Constant.varchar2_size)||(dataType.equals("VARCHAR")&&Integer.parseInt(dataLength) >= Constant.varchar2_size)){
                                  result.add(
          new String[]{columnName,dataType,dataLength});
                              }
                          }
                          resultSet.close();
                      } 
          catch (SQLException e1) {
                          e1.printStackTrace();
                      }
                  
          return result;
              5:取出4返回的信息,組織數(shù)據(jù),啟動(dòng)修改流程;
          for (List<String[]> table : tables) {
                      
          //tableInfo = tableInfo+  "\t表名:\t" ;
                      tableInfo = "\t表名:\t" ;
                      tableInfo 
          = tableInfo+table.get(0)[0]+ "\t主鍵 :\t "+table.get(1)[0]+" \t字段 :\t ";
                      String[] columns 
          = new String[table.size()-2];
                      
          for (int i =2;i<table.size();i++) {
                          
          if(table.get(i)==nullbreak ;
                          tableInfo 
          = tableInfo+table.get(i)[0]+"  "+table.get(i)[1];
                          
          if(table.get(i).length == 3) tableInfo = tableInfo+ "("+table.get(i)[2]+")";
                          tableInfo 
          = tableInfo + "\t";
                          String[] columnInfo 
          = table.get(i) ;
                          columns[i
          -2]=columnInfo[0];
                      }
                      tableInfo 
          = tableInfo+"\n";
                      System.out.println(tableInfo);
                      
                      
                      BufferedReader in 
          = new BufferedReader(new InputStreamReader(System.in));
                      String str 
          = "";
                          System.out.println(
          "   是否修改,請輸入'Y'或者'N' ! ");
                          
          try {
                              str 
          = in.readLine();
                          } 
          catch (IOException e) {
                              e.printStackTrace();
                          }
                          
          if(str.equalsIgnoreCase("y")){
                              blobOrVarchar2Clob(table.get(
          0)[0],table.get(1)[0],columns);
                          }
                  }
                  
                  System.out.println(
          "數(shù)據(jù)表修改處理邏輯結(jié)束!!!");

              6:修改流程:使用了門面模式,實(shí)現(xiàn)了“復(fù)制數(shù)據(jù)表結(jié)構(gòu)和數(shù)據(jù)到一個(gè)臨時(shí)表,先刪除要修改的列,再創(chuàng)建同名不同類型的列,從原始表中查出這一列的數(shù)據(jù),復(fù)制的臨時(shí)表中,刪除原始表,修改臨時(shí)表名為原始表名。”構(gòu)想。
              
          public static boolean blobOrVarchar2Clob(String srcTableName, String srcTableIdName, String columnNames) {
                  
          if (srcTableName == null || srcTableName.equals("")
                          
          || columnNames == null || columnNames.length == 0
                          
          || srcTableIdName == null || srcTableIdName.equals(""))
                      
          return false;
                  String printColumnNames 
          = "" ;
                  
          for (String columnName : columnNames) {
                      printColumnNames 
          += "  " +  columnName ;
                  }
                  System.out.println(
          "馬上就被修改  表名: "+srcTableName +  "   ,ID: " + srcTableIdName+"  字段:   "+printColumnNames);
                  Utils.createTempTable(srcTableName);
                  
          for (String columnName : columnNames) {
                      
          if(columnName==null||columnName.equals(""))continue ;
                      Utils.dropTempTableColumn(srcTableName, columnName);
                      Utils.addTempTableClobColumn(srcTableName, columnName);
                      Utils.copyDataOneColumn(srcTableName, columnName, srcTableIdName);
                  }
                  Utils.dropSrcTable(srcTableName
          +"_");
          //        Utils.dropSrcTable(srcTableName);
          //        Utils.modifyTempTableToSrcTable(srcTableName);
                  return true;
              }

              7:從原始表復(fù)制一列數(shù)據(jù)到臨時(shí)表:將數(shù)據(jù)寫入Map結(jié)構(gòu),再寫入臨時(shí)表。
                代碼片斷:
             
          HashMap<Integer, String> map = new HashMap<Integer, String>();
              
                      
          try {
                          
          while(resultSet.next()){
                              String content 
          = "";            
                                  
          int id = resultSet.getInt(srcTableIdName);
                                  
                                  
          int columnIndex = resultSet.findColumn(columnName);
                                   ResultSetMetaData resulSetMetaData 
          = resultSet.getMetaData();
                                   String columnTypeName 
          =resulSetMetaData.getColumnTypeName(columnIndex);
                                  
                                   
          if("VARCHAR2".equals(columnTypeName)||"VARCHAR".equals(columnTypeName)){
                                       content 
          = resultSet.getString(columnName);
                                   }
          else if("BLOB".equals(columnTypeName)){
                                          Blob blob 
          = resultSet.getBlob(columnName);
                                          
          if(blob==null)continue;
                                          content 
          = Utils.readBlobToString(blob);
                                   }
                                  map.put(id, content);
                          }
                          resultSet.close();
                      } 
          catch (SQLException e1) {
                          e1.printStackTrace();
                      }
                  
                  Set
          <Entry <Integer,String> > set = map.entrySet();
                  Iterator
          <Entry<Integer, String>> iterator =set.iterator();
                  
          while(iterator.hasNext()){
                      Entry
          <Integer, String> entry = iterator.next();
                  sql 
          = " update " + srcTableName + "" + " set "
                      
          + columnName + " = ? where " + srcTableName + "_."
                      
          + srcTableIdName + " = ? "  ;
                  PreparedStatement pstatement 
          =OracleDBUtil.getPreparedStatement(sql);
                  
          try {
                      pstatement.setString(
          1, entry.getValue());
                      pstatement.setInt(
          2, entry.getKey());
                      OracleDBUtil.executeUpdate(pstatement);
                      pstatement.close();




          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 营口市| 贺州市| 南宁市| 来凤县| 浦东新区| 榕江县| 临潭县| 阿克陶县| 萨迦县| 郧西县| 神池县| 奉节县| 玉环县| 山丹县| 许昌县| 临安市| 泽普县| 图们市| 开远市| 托克托县| 丹棱县| 新晃| 彩票| 牡丹江市| 海口市| 武胜县| 张掖市| 和龙市| 阜阳市| 新田县| 信宜市| 渭南市| 射洪县| 临泉县| 建德市| 枣强县| 嘉黎县| 胶州市| 文安县| 赫章县| 蓬莱市|