昨天有個同事在客戶的服務器上面弄數據庫,不小心執行了一條 sql 語句
1 TRUNCATE TABLE xxx
碉堡了吧,數據全沒了 - - ,然后就是在網上拼命的搜索關于數據恢復的軟件,搞了一下午還是回不來了。
需求來了后面老大就讓我寫一個作業每天備份一次數據庫,且只需要備份一些重要的表。
如何實現作業肯定不是難點,難點是怎么把需要的表的數據拿出來存放到新的數據庫中。
我首先就想到了sql中的導出數據功能,結果是可行的,可問題來了那個是使用工具導出的,用sql語句咋寫了,反正我是不會,有誰會的告訴一下哈。
后面在百度谷歌上找啊找啊,找到了個bcp
1 EXEC 數據庫名..xp_cmdshell 'bcp 表名 out 文件路徑 -c -T -U''賬號'' -P''密碼'''
結果發現這個只能導出文件,像txt,xls,csv等一些,不是我想要的mdf啊。(可能是我不會用落)
最終解決的方法1 select * into [備份的數據庫].dbo.表名 from [原數據庫].dbo.表名
意思是往[備份的數據庫]里增加一個表,表結構與數據都從[原數據庫]的表中復制(反正我是這么理解的 - -)
總體思路及代碼1 新建數據庫
數據庫名我是根據原始數據庫名加上當前日期命名的 testdb_bak_年_月_日
創建數據庫的代碼
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 @createBase14 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=014 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 end20 close test_Cursor21 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_xx15 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 @createBase21 exec (@createBase) --執行創建數據庫22 set @errorCount=@@ERROR23 if(@errorCount=0)24 begin25 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=036 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 end42 close test_Cursor43 DEALLOCATE test_Cursor44 end待完善的問題
不知道同學們發現沒有,如果想換需要備份的數據庫,則需要改兩個地方,注釋說明那里的2,3點,這兩個其實都是同一個數據庫名,下面的那個 use testdb,不知道能不能像執行sql語句一樣 exec ('use testdb'),如果可以的話那就換數據庫的話改下set @fromDataBaseName='testdb' 這句就O了。
作業接下來就是放到作業里面去了,這個直接上圖了。
1
2
3
4
最后面就O了。
新聞熱點
疑難解答