共計 8601 個字符,預計需要花費 22 分鐘才能閱讀完成。
本篇內容介紹了“從 MYSQL 到 oracle 的遷移以及備份的方法”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓丸趣 TV 小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
一、MYSQL 可以導入導出腳本,本來應該準備好數據庫的備份的初始化數據庫和初始化數據的兩個初始化腳本,經由 MYSQL 導出為一個 full.sql 的總的初始化腳本,用過 mysql 的都知道,導出的數據庫腳本中,包含了建庫、建表、以及插入數據的語句。需要分割成兩個:建庫、建表的初始化腳本和插入數據的初始化腳本。于是我寫了一個類,用于分割 SQL 腳本,在類中,我查找到 create table 開頭的后面緊跟著的字符串,就是表的名字,取出 insert 開頭的語句,改行就是插入數據的,于是,通過文件流讀取文件的每一行,如果是插入的取出來放入一個方法 convertInsertSQL 處理后寫入一個腳本文件 insert_data.sql 中,剩下的寫入一個腳本文件 create_table.sql 中, 方法 convertInsertSQL 對于插入語句做處理,因為腳本中的插入語句是批量插入的,insert into 表名 (列名) values(對應值),(對應值),(對應值),所以需要拆分成 insert into 表名(列名) values (對應值) 這樣的語句,所以我通過將前面 values(前的值截取后,對剩下的所有對應數據,進行通過),(用正則分割成 String 數組,對數組進行循環,每次追加組成插入語句,最后將插入語句全部返回后寫入文件流。
package com.test.file;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.HashMap;
import java.util.Map;
/**
* 將 mysql 數據庫導出的腳本
* 分割成為建庫和建表的兩個腳本
* @author gaofei
*
*/
public class MyFileReader {
/**
* @param args
*/
public static void main(String[] args) {
String full_sql_path= C:/Documents and Settings/gaofei/ 桌面 / 最終 mysql 腳本(12.15).sql
String create_sql_path= C:/Documents and Settings/gaofei/ 桌面 / 建立數據庫初始化.sql
String insert_sql_path= C:/Documents and Settings/gaofei/ 桌面 / 數據初始化.sql
try {
readFull_to_insert(full_sql_path, create_sql_path, insert_sql_path);
} catch (IOException e) {
System.out.println(文件讀取或寫入出錯
e.printStackTrace();
}
// String aa= insert into `templatetype`(`id`,`templatetypename`,`deflong`,`defdate`,`defvar`) values (0, 通用模板類型 ,0,NULL,NULL),(1, 首頁模板類型 ,0,NULL,NULL),(2, 欄目模板類型 ,0,NULL,NULL),(3, 專題模板類型 ,0,NULL,NULL),(4, 內容模板類型 ,0,NULL,NULL),(5, 留言模板類型 ,0,NULL,NULL),(6, 投票模板類型 ,0,NULL,NULL),(7, 特殊模板類型 ,0,NULL,NULL);
// String bb=full_to_part(aa);
// System.out.println(bb);
}
/**
* 將整體的導出的 mysql 腳本,拆分為建庫建表和插入數據的腳本
* 將其中的批量插入數據語句轉換為每條插入數據語句的腳本
* @param full_sql_path 原始全部導出的 mysql 腳本
* @param create_sql_path 拆出來的建庫建表的腳本
* @param insert_sql_path 拆出來的插入數據腳本
* @throws IOException
*/
private static void readFull_to_insert(String full_sql_path,String create_sql_path,String insert_sql_path) throws IOException{
File fullFile=new File(full_sql_path);
File createFile=new File(create_sql_path);
if(!createFile.exists())
createFile.createNewFile();
File insertFile=new File(insert_sql_path);
if(!insertFile.exists())
insertFile.createNewFile();
InputStreamReader isr=new InputStreamReader(new FileInputStream(fullFile), UTF-8
BufferedReader br=new BufferedReader(isr);
OutputStreamWriter osw_create=new OutputStreamWriter(new FileOutputStream(createFile), UTF-8
OutputStreamWriter osw_insert=new OutputStreamWriter(new FileOutputStream(insertFile), UTF-8
BufferedWriter bw_create=new BufferedWriter(osw_create);
BufferedWriter bw_insert=new BufferedWriter(osw_insert);
Map Integer, String allData=new HashMap Integer,String
String line=null;
int num=17;
while((line=br.readLine())!=null){
String lowerLine=line.toLowerCase();
if(lowerLine.startsWith( insert)){ // 在該語句下用來判斷插入數據的先后順序
if(lowerLine.indexOf( `sequenceblock`)!=-1){
allData.put(1, line);
}else if(lowerLine.indexOf( `operationlogtype`)!=-1){
allData.put(2, line);
}else if(lowerLine.indexOf( `website`)!=-1){
allData.put(3, line);
}else if(lowerLine.indexOf( `fucdefine`)!=-1){
allData.put(4, line);
}else if(lowerLine.indexOf( `role`)!=-1){
allData.put(5, line);
}else if(lowerLine.indexOf( `department`)!=-1){
allData.put(6, line);
}else if(lowerLine.indexOf( `cmsuser`)!=-1){
allData.put(7, line);
}else if(lowerLine.indexOf( `account`)!=-1){
allData.put(8, line);
}else if(lowerLine.indexOf( `accountrole`)!=-1){
allData.put(9, line);
}else if(lowerLine.indexOf( `flowdefine`)!=-1){
allData.put(10, line);
}else if(lowerLine.indexOf( `flowtask`)!=-1){
allData.put(11, line);
}else if(lowerLine.indexOf( `rolefucperm`)!=-1){
allData.put(12, line);
}else if(lowerLine.indexOf( `templategroup`)!=-1){
allData.put(13, line);
}else if(lowerLine.indexOf( `templatetype`)!=-1){
allData.put(14, line);
}else if(lowerLine.indexOf( `template`)!=-1){
allData.put(15, line);
}else if(lowerLine.indexOf( `contenttype`)!=-1){
allData.put(16, line);
}else{
allData.put(num++, line);
}
}else{
bw_create.append(line+ \r\n
}
}
for (int i = 1; i num; i++) {
if(allData.containsKey(i)){
bw_insert.append(full_to_part(allData.get(i)));
}
}
bw_create.flush();
bw_insert.flush();
br.close();
bw_create.close();
bw_insert.close();
}
// private static void setSequence(){
//
// }
/**
* 將一行批量插入的數據轉換為多行插入
* @param line
* @return
*/
private static String full_to_part(String line){
StringBuffer sb=new StringBuffer();
String lowerLine=line.toLowerCase();
int firstDan=lowerLine.indexOf(`
int firstQuot=lowerLine.indexOf((
String tableName=lowerLine.substring(firstDan, firstQuot);
System.out.println(————————– 開始轉換插入 —- +tableName+ — 的數據 ———-
int values_position=lowerLine.indexOf(values)+7;
String forward_line=line.substring(0, values_position);
String datas_line=line.substring(values_position,line.length()-1); // 得到后面插入的數據
String[] datas=datas_line.split( \\)\\,\\(// 根據),(分割為一個字符串數組
for (int i = 0; i datas.length; i++) {
String data=null;
if(datas.length==1){ // 如果只有一條數據,不會被分割的,數組就會只有一條數據
data=datas[i];
}else{
if(i==0) // 如果是第一條,那么后面需要追加一個括號
data=datas[i]+ )
else if(i==datas.length-1) // 如果是最后一條,需要在前面加一個括號
data= (+datas[i];
else // 如果是中間的數據,前后都需要加括號
data= (+datas[i]+ )
}
sb.append(forward_line); // 將 insert 字段名和 values 先行加入
sb.append(data+
sb.append(\r\n
}
sb.append(\r\n
return sb.toString();
}
}
這是通用方法,以后需要得到 MYSQL 的兩個初始化腳本就通過這個方法已轉換就可以。
二、Oracle 建表的問題沒有通過這個解決,可以通過 Hibernate 逆向生成。建表和表結構,表關系,都有了。
下面就是插入數據了:
關于 MYSQL 的 insert 腳本基本上和 Oracle 的一致,但是也有不一致,對于日期,對于一些符號 rsquo; 都是問題。將 MYSQL 的 insert 語句轉換成 ORACLE 的 insert 語句。
1、需要將 rsquo; 去掉,這個符號是在插入數據時的表名上括起來的,所以,將表名上的 rsquo; 都替換掉。
2、需要將 date 日期,經過函數 to_date(date,”yyyy-MM-dd”)轉換一下,所以我通過正則表達式來查找到所有的日期,還有一種日期,攜帶時分秒的日期,需要另一個正則,最后當然都是替換成為年月日就可以了。
package com.sql.convert;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class FromMYSQLInsertToOracleInsert {
/**
* 需要轉換一下地方:
* 將所有的表名以及列名中的 去掉
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
String mysql_file= C:/Documents and Settings/gaofei/ 桌面 /insertData.sql
String oracle_file= C:/Documents and Settings/gaofei/ 桌面 /oracle_insertData.sql
turnSQL(mysql_file, oracle_file);
}
private static void turnSQL(String mysql_file,String oracle_file) throws IOException{
File mysqlFile=new File(mysql_file);
File oracleFile=new File(oracle_file);
if(!oracleFile.exists())
oracleFile.createNewFile();
InputStreamReader isr=new InputStreamReader(new FileInputStream(mysqlFile), UTF-8
OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream(oracleFile), UTF-8
BufferedReader br=new BufferedReader(isr);
BufferedWriter bw=new BufferedWriter(osw);
String line=null;
while((line=br.readLine())!=null){
bw.append(convertString(line));
bw.append(\r\n
}
bw.flush();
br.close();
bw.close();
isr.close();
osw.close();
}
private static String convertString(String line){
line=line.replace(` ,
Pattern p=Pattern.compile(\\d{4}\\-\\d+\\-\\d+
Matcher m=p.matcher(line);
String date=null;
while(m.find()){
date=m.group(0);
line=line.replace(date, to_date( +date+ , yyyy-MM-dd)
}
p=Pattern.compile(\\d{4}\\-\\d+\\-\\d+\\s\\d+\\:\\d+\\:\\d+
m=p.matcher(line);
date=null;
while(m.find()){
date=m.group(0);
String newDate=date.substring(0,date.indexOf());
line=line.replace(date, to_date( +newDate+ , yyyy-MM-dd)
}
return line;
}
}
三、看似沒有問題了,直接執行腳本就沒問題了,但是問題又來了:
我是直接用控制開的 sqlplus 來訪問 Oracle 的,沒有工具,每次執行腳本,是通過 @腳本名.sql 來執行的,但是請注意如果是路徑太長,比如 @”C:/Documents and Settings/gaofei/ 桌面 /oracle_insertData.sql”路徑中間有空格需要加上””的,
執行報錯。很多錯:
1、關于數據中的 nbsp; 等這類的特殊,oracle 會認為是 plsql 中自定義的變量,當然會出問題了,所以需要設置 set define off,關掉自定義變量。
2、一個問題很少會有人用到,就是關于 Oracle 的插入數據,一個字段最多插入 2999 個字符。太多將會插入不進的。而我的數據都是模板或新聞,很多多是上萬,所以問題來了。沒有想到辦法。最后我是將很多的數據刪除的很短,插入成功后,通過程序一條條插入的。
遷移完成了,下面就是關于 Oracle 的備份問題了。www.2cto.com
說是可以準備 SQL 腳本,但是腳本到時候還會是 INSERT 語句,到時候又不能插入了。
所以是通過 ORACLE 的備份命令,備份出 DMP 文件。
剛開始是用 SYSTEM 用戶直接備份的,但是會有很多的系統表,這是不符合要求的。于是建立一個用戶 future,用 future 用戶逆向生成表結構、表關系。然后通過賦予 futureDBA 權限,通過 insert into sequenceblock select * from system.sequenceblock; 將所有表中有數據的表都從 system 導入到 future 用戶中。
這樣表就再 future 用戶的指定表空間中建立出來了。
通過 future 直接備份數據。有兩種備份方式。
$exp future/ylzxdb1219@ylzxdb file=D:/future_final.dmp full=y;
以 future 身份導出了所有庫的信息
$exp future/ylzxdb1219@ylzxdb file=D:/future_user.dmp owner=future;
以 future 的身份導出了 future 用戶中所有的數據。
但是 future 有 DBA 權限,所以會再備份時將系統表備份。所以推薦第二種方式。導出的只是當前用戶 future 的所有表的備份。
導入數據:
$imp future/ylzxdb1219@ylzxdb fromuser=future touser=future ignore=y file=D:/future_user.dmp;
(注:例句是將的備份文件放在了 D: 盤下的 future.user.dmp 文件)
“從 MYSQL 到 oracle 的遷移以及備份的方法”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注丸趣 TV 網站,丸趣 TV 小編將為大家輸出更多高質量的實用文章!