初始腳本
Get-SqlDatabase -ServerInstance localhost | Where { $_.Name -ne 'tempdb' } | Backup-SqlDatabase
使用上面的命令我們就能每天備份數據庫到指定路徑去。當然,這只是一個實例,加入打算備份每一個數據庫在備份在各自的數據庫實例的服務器上,又該如何修改上面的語句那?
目的是批量備份多個實例的數據庫,注意這里需要提前把數據庫實例存儲在一個地方,然后循環遍歷出來,代碼如下:
foreach $RegisteredSQLs IN dir -recurse SQLSERVER:\SQLRegistration\'Database Engine Server Group'\Host\ | where {$_.Mode -ne 'd'} ) { Get-SqlDatabase -ServerInstance $RegisteredSQLs.Name | Where { $_.Name -ne 'tempdb' } | Backup-SqlDatabase }
代碼可是真心簡短。當然這不足以促使你用PS來替代現有的數據庫備份,只是提供了一個一次性備份數據庫的簡便方式。對於數據庫的常規備份來說,你或許不會特別擔心,因為這些備份可能由系統管理員或者SAN來負責。假如你的工作中包含了備份數據庫,那么使用PowerShell來備份數據庫就是一種值得使用的方式了,尤其是當你數據庫服務器上都有PowerShell的時候。
這是PowerShell最為重要的技巧之一
接下來,考慮當需要一次性備份數據庫時,大多數時候我遇到的備份都是只備份部分數據庫,因此按需求從一個列表中備份數據庫是一個不錯的方式。型號ps有一個叫做Out-GridView的命令,方便我們做這樣的操作。上面的腳本中使用where子句,這里我們可以使用Out-GridView -PassThru代替where,並保證結尾用一個“|”來結束。代碼如下:
Get-SqlDatabase -ServerInstance localhost | Out-GridView -PassThru | Backup-SqlDatabase
對我而言-PassThru 參數是個非常有用的命令參數。方便我們僅僅通過一個參數修改完成命令。上面的腳本中這個參數其實就是數據庫名稱。進一步而言也可能是數據表,SQL Server Agent Jobs,CSV 文件等等。
Out-GridView 如何使用
下面這個例子使用了Out-GridView 命令,這個場景下,我選擇三個數據庫,然后會只備份我選擇的三個。

另一個很有用的功能就是過濾。如果使用了過濾欄,將會查詢每一個展示名字中包含我輸入的文字的數據庫。為了精確查找,我們可以點擊“Add Criteria”來選擇過濾的字段,這樣就能只過濾數據庫的名字。

接下來點擊DW詞條,會展示數據庫查詢后的結果,並高亮選中行。

一旦點擊ok,將會看到4個數據庫被自動備份。

PowerShell 變得更容易
如果你已經相信PS至少對於熱備份是更簡便的備份方式,我接下來在提供幾個備份選項。再次返回最上面的備份例子中,如在備份指令后添加一個-CompressionOption參數,然后空格會顯示幾個可選參數,如on、off、default等,如圖:

注意:這是在PowerShell ISE中,其他的編輯器可能會有不同的彈出參數的的觸發。比如我嘗試了在PowerShell console 中需要用“Crtl”+空格鍵才會觸發。
Get-SqlDatabase -ServerInstance localhost | Out-GridView -PassThru | Backup-SqlDatabase -CompressionOption On
通過這個指定可以壓縮備份結果,減少不必要的空間。
有趣的腳本參數和實踐
這里先要介紹一下-Script ,在備份語句的最后添加這個參數將會允許輸出指令,不必等到實際執行的時候。這就讓我們可以不用等到備份完成就可以看到腳本。如下圖所示,其實我們的PS腳本就是封裝了T-SQL腳本而已。

更多備份參數
讓我們看看這個指令其他的可選參數。如果我想能夠了解更多信息可以使用Get-Help指令。
Get-Help -Full Backup-SqlDatabase
也可以找到-ShowWindow 選項,這個參數會彈出幫助文件在一個獨立窗口中。使用搜索來方便查找有用的參數。
Get-Help -ShowWindow Backup-SqlDatabase
-BackupAction
使用這個參數可以選擇備份數據庫、文件或者是日志。默認為完整備份數據庫,因此如果你不指定那就為完整備份。如果打算做一個差異備份,使用-Incremental 參數。

(注意這個可選中沒有差異備份,因為差異備份用的是獨立參數-Incremental )
-DatabaseFile & –DatabaseFileGroup
Backup-SqlDatabase 指令還能夠備份單一數據文件或者文件組。如果選擇Files作為-BackupAction 參數的可選項,你會需要增加-DatabaseFile或者 -DatabaseFileGroup ,根據數據文件或者文件組名稱來備份。
-BackupFile
現在,你已經選擇了備份的類型以及備份內容。默認情況是備份為.bak后綴的文件。這是附加備份這樣可以不刪除文件的情況下附加備份,相應的空間占用會越來越大。這個時候你可以用-BackupFile 參數來修改路徑,或者直接備份到Azure存儲。
如果需要找到默認備份實例的默認備份路徑,可以執行下面的命令:
(Get-Item sqlserver:\sql\localhost\default\).BackupDirectory
對於備份文件的名字我一般采用日期模式,這樣確保文件不會充滿。使用下面來獲得名字:
Get-Date -UFormat %Y%m%d%H%M
綜上,我們需要添加一個循環所有備份語句指令,以便於我們可以修改備份文件名字。詳細代碼如下:
<# 備份素有數據庫並提供包含文件和日期的文件名 *> Get-SqlDatabase -ServerInstance localhost | Where { $_.Name -ne 'tempdb' } | foreach{ Backup-SqlDatabase -DatabaseObject $_ -CompressionOption On -BackupFile "$($_.NAME)_db_$(Get-Date -UFormat %Y%m%d%H%M).bak" -Script}
-ServerInstance & -Database
我們沒有提供-ServerInstance & -Database 兩個參數,因為例子中使用了Get-SqlDatabase 指令已經傳遞了包含數據庫對象的數組,$_包含了這些參數被以屬性的方式保存。Backup-SqlDatabase 指令使用了-DatabaseObject 參數默認去使用。
如果打算備份一個數據庫,你可以使用下面的方式而不去調用Get-SqlDatabase。
Backup-SqlDatabase -ServerInstance localhost -Database msdb
-PassThru
這里要說一下pipeline,是否已經在pS中遇到過,並且調試進程。你可以使用-PassThru 參數來看一下管道。這也是提供一個機會來看我們發出命令參數被編譯為什么?
Backup-SqlDatabase -ServerInstance localhost -Database msdb -Script -PassThru;

SQL Provider
最后一個選項就是你可以在SQL Server PowerShell Provider中運行這個命令。能夠通過打開PowerShell ISE 得到SQL Provider,然后運行導入模塊 Import-Module SqlServer 或者在數據庫節點中右擊數據庫。

這里,您可以通過輸入backup-sqldatabase和想要備份的數據庫的名稱來備份一個數據庫。如果您需要在備份完成后啟動其他任務,則此選項可能是有益的。或者使用下面的代碼樣例來備份這個實例中的所有數據庫。

If you choose to use the ISE, VS Code (or another rich PowerShell editor) to get to the SQL Provider you will want to start out like this
如果你選擇使用ISE獲得SQLProvider,執行下面指令:
Import-Module SqlServer; CD SQLSERVER:\SQL\localhost\default\Databases\
總結
我希望利用PS來備份數據庫的指令Backup-SqlDatabase cmdlet 能夠給大家提供便利。提供給大家一個比起T-sql更便捷的方式。同時可以用它來輸出T-sql語句。
本文中顯示的所有代碼都是使用SqlServer PowerShell模塊完成的,該模塊使用SSMS 2016(16.5+),而我的機器運行的是PowerShell的5.1版本。除此之外我還測試了2012 在PS3.0也是可行的。
