LocalDB - 在LocalDB上使用SSMS還原資料庫產生錯誤

06 November 2012 — Written by Sky Chang
#SQL Server

2012/11/09 更新 – 保哥的這篇文章,有教大家手動修改註冊碼,來修正這個錯誤喔,而Terry哥也提供了一篇文章,利用T-SQL去修改註冊碼!!大家有興趣也可以連過去看看=V=

很久很久以前,有一個案子 ( 好像在說故事一樣… ),那時後再使用SQL Server Express當作本機的資料庫開發;而最近,因為需求的關係,需要進行一些調整,老實說,我也懶的(不想)去裝SQL Server Express,畢竟用LocalDB用的好好的,為啥還要去裝呢!?於是,就先把資料從SQL Server Express備份下來 ( 不要問我,為什麼不直接拷貝mdf和log檔案..因為小弟我直覺就選擇了備份XDD ),然後拿到現在的電腦上,準備利用SSMS對LocalDB進行匯入…

然後悲劇就發生了… ( 所以這是一個悲慘的故事… )

image

設定 'Microsoft.SqlServer.Management.Smo.Settings' 無法使用屬性 BackupDirectory。此物件可能沒有此屬性,或因為存取權限不足而無法擷取。 (Microsoft.SqlServer.Smo)

或是選擇還原資料庫,也是出現同樣的錯誤。( 當然,我不是要還原到msdb..這裡只是隨便選一個,重點是上面的紅色框框。 )

image

好吧,既然發生錯誤,就要去尋找怎樣解決,於是找到了這篇;內文大致上是說,因為路徑的關係,所以要去改註冊碼,要不然就是要用T-SQL解決,而目前保哥也提供了一篇文章,來教大家如何修改註冊碼,而Terry哥也提供了一篇文章,則是利用T-SQL去修改註冊碼!!有興趣的可以連過去看看,小弟這邊就不針對註冊碼的地方做教學了 ( 沒事不要和那幾位神人PK~~ )。

OK,不管怎樣,小弟是沒去改路徑,而且既然T-SQL可以解決,那就用T-SQL吧,反正小弟我也不是一天到晚要復原XDD,也順便學習一下T-SQL…( 路人 : 我看其實是寫這篇文章的時候,根本沒去測試註冊碼的方式…還那麼多理由… )。OK,不管怎樣,那些是神人的做法XDD,平民的小弟我,還是用T-SQL就好!!,接下來,我們先看一下這個T-SQL。

RESTORE DATABASE FROM DISK = '' WITH NORECOVERY,
MOVE 'example_dat' TO 'C:\Temp\.mdf', 
MOVE 'example_log' TO 'C:\Temp\.ldf'

OK,相信如果是DBA,大概就已經知道如何還原了,後面也可以不用往下看了XDD,( 後面就單純介紹這個指令而已了。 )。

那這個T-SQL是甚麼意思呢,簡單的說,就是恢復Restore資料庫(廢話!!),而要恢復的這個資料庫來源來自於哪邊,所有DISK後面要接位置;例如DISK = ‘C:\Temp\ss.bak';接下來的WITH,表示我們後面還要加上一些還原的選項,例如這邊我們的NORECOVERY,就是代表著,要執行NORECOVERY的作業 ( 好啦,後續會講到…);而Move表示我們要將原本SQL Server的mdf和ldf檔案的位置,改變到新的位置。

嗯,有聽沒有懂!?,那我們先執行一下下面這個指令看看;我們可以利用這個指令列出備份檔案的資料。

RESTORE FILELISTONLY FROM 
DISK='C:\Temp\SC' 

會出現如下圖,大家可以看到下面第一個是LogicalName( 這邊資料很抱歉,必須隱藏一下,總之就是SxxxxData和SxxxLog ),而第二個是PhysicalName,也就是原本mdf和ldf檔案存放的位置;那大家可以發現甚麼?是的,原本的mdf和ldf位置,是放在SQL Server Express的預設目錄下面。

image

所以我們回到剛剛的T-SQL,大家應該就可以了解的到,為什麼要用Move了吧,因為原本的備份檔,mdf和ldf檔的位置是在SQL Server Express的預設目錄下,而小弟我因為要移到新的電腦上,所以要存放mdf和ldf的位置,就和原本的不同了,所以要使用Move指令改變位置,所以我們的T-SQL會改成這樣;Move後面接的是LogicName的名稱,也就是Sxxxx_Data,而To接的就是要搬到那裡,然後也順便把DISK填入備份檔的路徑。

RESTORE DATABASE FROM DISK = 'C:\Temp\SC' WITH NORECOVERY, 
MOVE 'Sxxxx_Data' TO 'C:\Temp\Sxxxx.mdf', 
MOVE 'Sxxxx_Log' TO 'C:\Temp\Sxxxx.ldf'

另外,備註一下,如果Sxxxx_Data填錯,則會出現以下錯誤,所以我們才要用RESTORE FILELISTONLY來列出名稱。

邏輯檔案 'xx' 不屬於資料庫 xx' 的一部分。請使用 RESTORE FILELISTONLY 列出邏輯檔案名稱。

所以,這樣就好了嗎!?如果這樣執行下去,你會發現,DB的確是還原了…但會出現如下圖;式的會一直卡在"正在還原"。

image

那是為什麼呢?其實是因為NORECOVERY這個參數的關係,這個參數的意思,官方是這樣寫的。

指示還原作業不回復任何未認可的交易。 如果稍後必須套用另一個交易記錄,請指定 NORECOVERY 或 STANDBY 選項。 如果 NORECOVERY、RECOVERY 和 STANDBY 三者都沒有指定,預設值就是 RECOVERY。 在使用 NORECOVERY 選項的離線還原作業期間,無法使用資料庫。

就如官方的最後段話,使用NORECOVERY後,會無法使用資料庫;其實那是因為SQL Server的還原機制有三種,不過再談下去,就越拉越遠了XDD,大家可以參考Cary的這篇,或是Funkent的這篇

總之,因為小弟我的備份,是全部備份下來,也沒使用差異備份,所以我們要把NORECOVERY改成RECOVERY,要把T-SQL改成這樣。

RESTORE DATABASE SDB
FROM DISK = 'C:\Temp\SC' 
WITH RECOVERY,
MOVE 'Sxxxx_Data' TO 'C:\Temp\Sxxxx.mdf', 
MOVE 'Sxxxx_Log' TO 'C:\Temp\Sxxxx.ldf' 

這樣又可以了,如下圖,因為SQL Server Express是舊版的db,所以也會自動升級。

image

就這樣,完成了人生第一次的T-SQL 備份還原XDDD ( 話說有點撈過界了XDDD )

後記

老實說,雖然有點撈過界XDD,但也學習到不少東西,希望DBA高手們,不要鞭我喔XDDD

參考資料

Sky & Study4.TW