sql 做業+遊標 自動備份數據庫

前言

昨天有個同事在客戶的服務器上面弄數據庫,不當心執行了一條 sql 語句    sql

1 TRUNCATE TABLE xxx

碉堡了吧,數據全沒了  - - ,而後就是在網上拼命的搜索關於數據恢復的軟件,搞了一下午仍是回不來了。 shell

需求來了

後面老大就讓我寫一個做業天天備份一次數據庫,且只須要備份一些重要的表。數據庫

如何實現

做業確定不是難點,難點是怎麼把須要的表的數據拿出來存放到新的數據庫中。服務器

我首先就想到了sql中的導出數據功能,結果是可行的,可問題來了那個是使用工具導出的,用sql語句咋寫了,反正我是不會,有誰會的告訴一下哈。工具

後面在百度谷歌上找啊找啊,找到了個bcpfetch

1 EXEC 數據庫名..xp_cmdshell 'bcp 表名 out 文件路徑 -c -T -U''帳號'' -P''密碼'''

結果發現這個只能導出文件,像txt,xls,csv等一些,不是我想要的mdf啊。(多是我不會用落)spa

最終解決的方法 

1 select * into [備份的數據庫].dbo.表名  from [原數據庫].dbo.表名

意思是往[備份的數據庫]裏增長一個表,表結構與數據都從[原數據庫]的表中複製(反正我是這麼理解的 - -)日誌

整體思路及代碼

   1 新建數據庫code

        數據庫名我是根據原始數據庫名加上當前日期命名的  testdb_bak_年_月_日blog

        建立數據庫的代碼        

 1 declare @fromDataBaseName nvarchar(50) --原數據庫名稱
 2 set @fromDataBaseName='testdb'
 3 declare @errorCount int --錯誤數
 4 declare @yearMonthDay nvarchar(50) --年_月_日
 5 select @yearMonthDay=Datename(year,GetDate())+'_'+Datename(month,GetDate())+'_'+Datename(day,GetDate())
 6 declare @baseName nvarchar(50)--數據庫名稱
 7 set @baseName=@fromDataBaseName + '_bak_' + @yearMonthDay --數據庫名稱爲 gpsdb_bak_xx_xx_xx
 8 
 9 declare @createBase nvarchar(500) --建立數據庫用的sql語句
10 set @createBase='create database [' + @baseName + ']
11  on  primary(name=['+ @baseName + '_Data],filename=''D:\GpsdbBak\' + @baseName + '_Data.mdf'',size=5mb,maxsize=100mb, filegrowth=15%)
12 log on(name=['+ @baseName + '_log],filename=''D:\GpsdbBak\' + @baseName + '_log.ldf'',size=2mb,filegrowth=1mb)'
13 print @createBase
14 exec (@createBase) --執行建立數據庫
15 set @errorCount=@@ERROR

    2 獲取原數據庫中通過刷選的表而後複製到上面新建的表中

          獲取原數據庫中全部的表名,sql 語句以下

use [testdb]
select name from sysobjects where type = 'U' and --獲取全部表名
   (CHARINDEX('gps_position_',name)=0 and --帶有這個的表不要
   CHARINDEX('buf',name)=0 and --臨時表不要
   name <> 'gps_log')  --日誌表不要
   ORDER BY Name 

     3 遊標

          獲得了全部表以後確定就是最後的關鍵步驟,複製表到新數據庫,這裏我是用遊標實現的。

 1 use [testdb]  
 2    declare test_Cursor  cursor local for --定義一個遊標
 3    
 4    select name from sysobjects where type = 'U' and --獲取全部表名
 5    (CHARINDEX('gps_position_',name)=0 and --帶有這個的表不要
 6    CHARINDEX('buf',name)=0 and --臨時表不要
 7    name <> 'gps_log')  --日誌表不要
 8    ORDER BY Name 
 9   
10    open test_Cursor--打開遊標
11    declare @table_name nvarchar(50)
12    fetch next from test_Cursor into @table_name 
13     while @@FETCH_STATUS=0
14      begin 
15       if(@table_name<>'')
16        begin      
17         exec ('select * into [' + @baseName +'].dbo.' + @table_name +' from ['+ @fromDataBaseName +'].dbo.' + @table_name) --關鍵的一語句代碼 
18       fetch next from test_Cursor into @table_name 
19      end
20 close test_Cursor
21 DEALLOCATE test_Cursor

 完整代碼

 1 /*
 2 備份數據腳本,將@fromDataBaseName(原數據庫備份到@baseName數據庫中)
 3 需注意的地方
 4 1:須要在D盤創建一個名爲GpsdbBak的文件夾
 5 2:須要根據實際狀況給fromDataBaseName變量賦值
 6 3:找到use 修改use後面的數據庫名稱爲實際狀況下的
 7 */
 8 declare @fromDataBaseName nvarchar(50) --原數據庫名稱
 9 set @fromDataBaseName='testdb'
10 declare @errorCount int --錯誤數
11 declare @yearMonthDay nvarchar(50) --年_月_日
12 select @yearMonthDay=Datename(year,GetDate())+'_'+Datename(month,GetDate())+'_'+Datename(day,GetDate())
13 declare @baseName nvarchar(50)--數據庫名稱
14 set @baseName=@fromDataBaseName + '_bak_' + @yearMonthDay --數據庫名稱爲 gpsdb_bak_xx_xx_xx
15 
16 declare @createBase nvarchar(500) --建立數據庫用的sql語句
17 set @createBase='create database [' + @baseName + ']
18  on  primary(name=['+ @baseName + '_Data],filename=''D:\GpsdbBak\' + @baseName + '_Data.mdf'',size=5mb,maxsize=100mb, filegrowth=15%)
19 log on(name=['+ @baseName + '_log],filename=''D:\GpsdbBak\' + @baseName + '_log.ldf'',size=2mb,filegrowth=1mb)'
20 print @createBase
21 exec (@createBase) --執行建立數據庫
22 set @errorCount=@@ERROR
23 if(@errorCount=0)
24 begin
25 use [testdb]  
26    declare test_Cursor  cursor local for --定義一個遊標   
27    select name from sysobjects where type = 'U' and --獲取全部表名
28    (CHARINDEX('gps_position_',name)=0 and --帶有這個的表不要
29    CHARINDEX('buf',name)=0 and --臨時表不要
30    name <> 'gps_log')  --日誌表不要
31    ORDER BY Name   
32    open test_Cursor--打開遊標
33    declare @table_name nvarchar(50)
34    fetch next from test_Cursor into @table_name 
35     while @@FETCH_STATUS=0
36      begin 
37       if(@table_name<>'')
38        begin      
39         exec ('select * into [' + @baseName +'].dbo.' + @table_name +' from ['+ @fromDataBaseName +'].dbo.' + @table_name) --關鍵的一語句代碼 
40       fetch next from test_Cursor into @table_name 
41      end
42 close test_Cursor
43 DEALLOCATE test_Cursor
44 end

 待完善的問題

 不知道同窗們發現沒有,若是想換須要備份的數據庫,則須要改兩個地方,註釋說明那裏的2,3點,這兩個其實都是同一個數據庫名,下面的那個 use testdb,不知道能不能像執行sql語句同樣 exec ('use testdb'),若是能夠的話那就換數據庫的話改下 set @fromDataBaseName='testdb' 這句就O了。

做業

接下來就是放到做業裏面去了,這個直接上圖了。

1

2

 3

4

最後面就O了。

相關文章
相關標籤/搜索