使用java實(shí)現(xiàn)備份和恢復(fù)SQLServer表數(shù)據(jù)
需求
近來工作中遇到一個問題,內(nèi)網(wǎng)辦公系統(tǒng)中的數(shù)據(jù)需要導(dǎo)出到外網(wǎng)中進(jìn)行查詢,外網(wǎng)的數(shù)據(jù)庫中還有一些表存儲外網(wǎng)的數(shù)據(jù),因此無法使用全庫備份恢復(fù)功能來滿足需求。即只從內(nèi)網(wǎng)數(shù)據(jù)庫中導(dǎo)出若干表的內(nèi)容至外網(wǎng)數(shù)據(jù)庫的對應(yīng)表。
其他解決方案:使用SQL Server自身的導(dǎo)出SQL語句的方法其實(shí)也可以,但是涉及到幾十個表,一一手工導(dǎo)出工作量較大。
因此自己寫了個函數(shù),將內(nèi)網(wǎng)中的表數(shù)據(jù)導(dǎo)出,根據(jù)數(shù)據(jù)生成insert into 語句,然后使用批處理的方式導(dǎo)入到外網(wǎng)數(shù)據(jù)庫中。
1.表結(jié)構(gòu)的分析
生成insert語句時,不得不面對的是引號的使用,對于int等類型無需引號,但是對于char、text等必須加上引號,一個表動輒幾十個字段,人工用數(shù)組等方式記錄字段的類型、名稱再進(jìn)行處理,也比較耗費(fèi)精力,尤其是數(shù)據(jù)表的結(jié)構(gòu)時常還在變化,而且是另一個開發(fā)公司在維護(hù),何時變化也不得而知。這里通過分析建表語句完成了自動的字段類型的對應(yīng),從而大大減輕了人工維護(hù)字段及其類型的工作量。
譬如建表語句如下(在SQL Server企業(yè)管理器中選中表,Ctrl+C即可得到),這里存放一個文件中:
CREATE TABLE [Import_BizDescrs] ( [DescrId] [char] (10) COLLATE Chinese_PRC_CI_AS NULL , [DescrType] [char] (20) COLLATE Chinese_PRC_CI_AS NULL , [DescrAt] [datetime] NULL , [Descr] [text] COLLATE Chinese_PRC_CI_AS NULL , [DescrBy] [char] (20) COLLATE Chinese_PRC_CI_AS NULL , [BizId] [char] (10) COLLATE Chinese_PRC_CI_AS NULL , [SampId] [char] (20) COLLATE Chinese_PRC_CI_AS NULL , [AssistTaskId] [char] (20) COLLATE Chinese_PRC_CI_AS NULL , [CreatePerson] [char] (20) COLLATE Chinese_PRC_CI_AS NULL , [CreateDate] [datetime] NULL , [UpdatePerson] [char] (20) COLLATE Chinese_PRC_CI_AS NULL , [UpdateDate] [datetime] NULL ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] GO
從以上文字中,做出如下處理,即可獲得表名、字段名、字段類型以及附帶的是否需要引號。
public static void exportTableDataByCreateSQL(String createSQLFileName){
ArrayList <String> fieldNames = new ArrayList<String>();
ArrayList <String> fieldtypes = new ArrayList<String>();
ArrayList <Boolean> needQuotationMark = new ArrayList<Boolean>();
String tableName = "";
String filePath = "C:\\importSQLs\\";
String tmpString;
try {
BufferedReader reader = new BufferedReader(new FileReader(createSQLFileName));
String line = reader.readLine();
//從第一行獲取表名
tableName = line.substring(line.indexOf("[")+1,line.indexOf("]"));;
System.out.println(tableName) ;
//后面獲取其他信息
while ((line = reader.readLine()) != null) {
if(line.startsWith(")")){
break;
}
tmpString = line.substring(line.indexOf("[")+1,line.indexOf("]"));
fieldNames.add(tmpString);
line = line.substring(line.indexOf("]")+1);
tmpString = line.substring(line.indexOf("[")+1,line.indexOf("]"));
fieldtypes.add(tmpString);
if(tmpString.contains("char")
||tmpString.contains("text")
||tmpString.contains("datetime")){
needQuotationMark.add(true);
}else{
needQuotationMark.add(false);
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}2.備份表
獲取到完整的字段、字段屬性后,就可以開始生成SQL文件了,對于值為null的數(shù)據(jù),略去相應(yīng)的插入語句,同時由于是全表全量導(dǎo)入,開始時增加了delete from tableName;的語句
全部代碼如下:
public static void exportTableDataByCreateSQL(String createSQLFileName){
ArrayList <String> fieldNames = new ArrayList<String>();
ArrayList <String> fieldtypes = new ArrayList<String>();
ArrayList <Boolean> needQuotationMark = new ArrayList<Boolean>();
String tableName = "";
String filePath = "C:\\importSQLs\\";
String tmpString;
try {
BufferedReader reader = new BufferedReader(new FileReader(createSQLFileName));
String line = reader.readLine();
//從第一行獲取表名
tableName = line.substring(line.indexOf("[")+1,line.indexOf("]"));;
//后面獲取其他信息
while ((line = reader.readLine()) != null) {
if(line.startsWith(")")){
break;
}
tmpString = line.substring(line.indexOf("[")+1,line.indexOf("]"));
fieldNames.add(tmpString);
line = line.substring(line.indexOf("]")+1);
tmpString = line.substring(line.indexOf("[")+1,line.indexOf("]"));
fieldtypes.add(tmpString);
if(tmpString.contains("char")
||tmpString.contains("text")
||tmpString.contains("datetime")){
needQuotationMark.add(true);
}else{
needQuotationMark.add(false);
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//開始生成insert語句
Connection conn;
try {
Class.forName("net.sourceforge.jtds.jdbc.Driver");
conn = DriverManager.getConnection(GlobalVar.ConnURL,GlobalVar.ConnUser,GlobalVar.ConnPWD);
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM " + tableName);
FileWriter writer = new FileWriter(filePath + tableName+".lims2", false);
BufferedWriter bufferedWriter = new BufferedWriter(writer);
bufferedWriter.write("delete from "+tableName + ";");
bufferedWriter.newLine();
while (rs.next()) {
String FieldsString="";
String ValuesString="";
for(int i=0; i< needQuotationMark.size();i++){
tmpString = rs.getString(fieldNames.get(i));
if(tmpString != null){
if(FieldsString.equals("")){
FieldsString += fieldNames.get(i);
ValuesString += (needQuotationMark.get(i)?"'":"")+ tmpString.trim() +(needQuotationMark.get(i)?"'":"");
}else{
FieldsString += "," + fieldNames.get(i);
ValuesString += "," + (needQuotationMark.get(i)?"'":"")+ tmpString.trim() + (needQuotationMark.get(i)?"'":"");
}
}
}
bufferedWriter.write("insert into "+ tableName + "("+FieldsString+") values("+ValuesString+");");
bufferedWriter.newLine();
}
bufferedWriter.close();
writer.close();
rs.close();
stmt.close();
conn.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}調(diào)用以上函數(shù)時,只需將保存建表語句的sql文件位置作為參數(shù)即可,在本項目中,生成的sql文件以.lims2結(jié)尾。
3.還原表
由于生成的表數(shù)據(jù)文件較多,這里寫了個批處理文件,將導(dǎo)出的表數(shù)據(jù)文件和該批處理文件一起拷貝到外網(wǎng)服務(wù)器中,運(yùn)行批處理即完成了導(dǎo)入操作。以后準(zhǔn)備寫個上傳的頁面,省去了遠(yuǎn)程桌面的麻煩。批處理文件如下:
osql -S 127.0.0.1 -U 用戶名 -P 密碼 -d lims2 -i Import_table1.lims2 -o Rst_Import_table1.log
osql -S 127.0.0.1 -U 用戶名 -P 密碼 -d lims2 -i import_table2.lims2 -o Rst_import_table2.log
osql -S 127.0.0.1 -U 用戶名 -P 密碼 -d lims2 -i Import_table3.lims2 -o Rst_Import_table3.log
osql -S 127.0.0.1 -U 用戶名 -P 密碼 -d lims2 -i import_table4.lims2 -o Rst_import_table4.log
osql -S 127.0.0.1 -U 用戶名 -P 密碼 -d lims2 -i import_table5.lims2 -o Rst_import_table5.log
........
結(jié)語
此方法適用于同步部分表而不是整庫的情況,尤其是兩個數(shù)據(jù)庫無法直接通信,需要手工同步的場景。
到此這篇關(guān)于使用java實(shí)現(xiàn)備份和恢復(fù)SQLServer表數(shù)據(jù)的文章就介紹到這了,更多相關(guān)java備份和恢復(fù)SQLServer表數(shù)據(jù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Mybatis Plus 實(shí)現(xiàn)批量插入的示例代碼
本文主要介紹了Mybatis Plus 實(shí)現(xiàn)批量插入的示例代碼,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-09-09
JAVA的LIST接口的REMOVE重載方法調(diào)用原理解析
這篇文章主要介紹了JAVA的LIST接口的REMOVE重載方法調(diào)用原理解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-10-10
Elasticsearch 映射參數(shù)詳解 fields
這篇文章主要介紹了fields Elasticsearch 映射參數(shù)fields,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07
Spring?Boot緩存實(shí)戰(zhàn)之Redis?設(shè)置有效時間和自動刷新緩存功能(時間支持在配置文件中配置)
這篇文章主要介紹了Spring?Boot緩存實(shí)戰(zhàn)?Redis?設(shè)置有效時間和自動刷新緩存,時間支持在配置文件中配置,需要的朋友可以參考下2023-05-05
解決IDEA2021版compiler.automake.allow.when.app.running不存在的問題
很多文章介紹IntelliJ IDEA開啟熱部署功能都會寫到在IntelliJ IDEA中的注冊表中開啟compiler.automake.allow.when.app.running選項,此選項在IntelliJ IDEA 2021.2之后的版本遷移到高級設(shè)置中,下面看下設(shè)置方法2021-09-09

