Sql-Server

SQL Server 表名以 # 開頭,在使用者數據庫中,不在 tempdb 中,不是臨時表

  • December 13, 2017

不知何故,幾十年前,在我們的數據庫中創建了一個以#. 它顯示在應用程序數據庫下的對象資源管理器中,而不是tempdb. 出於某種原因,Azure 不會像這樣導入數據庫。

我們不能刪除它、重命名它或與之互動。我已經嘗試過從對象資源管理器中刪除、*腳本拖放、從 GUI中重命名,但它們都沒有奏效。*

我們使用的是 SQL 2008 R2。

drop table [*app*].[dbo]."#OBSOLETE";

Database name '*app*' ignored, referencing object in tempdb.
Msg 3701, Level 11, State 5, Line 1
Cannot drop the table '#OBSOLETE', because it does not exist or you do not 
have permission.

exec sp_rename "dbo.#OBSOLETE", "dbo.obsolete"

Msg 15225, Level 11, State 1, Procedure sp_rename, Line 338
No item by the name of 'dbo.#OBSOLETE' could be found in the current database '*app*', given that @itemtype was input as '(null)'.

我們如何殺死這個對象,以便我們可以將它遷移到 Azure?

鑑於:

  1. sp_rename使用對象名稱而不是對象 ID,
  2. 我們不能使用對象名稱,因為它以 a 開頭,#並且被解釋為具有特殊含義並且處理方式不同,
  3. 所有其他選項都已用盡

您應該嘗試通過專用管理控制台 (DAC) 連接直接編輯底層系統目錄表:

  1. 獲取該object_id表的。
  2. 在單使用者模式下重啟實例。這是為了能夠直接更新系統表(即不需要使用 DAC 連接)。
  3. 通過專用管理控制台連接進行連接。您可以通過在命令提示符視窗中執行以下命令在 SQLCMD 互動式會話中執行此操作:
C:\> SQLCMD -A -E

或者,使用以下命令直接連接到數據庫:

C:\> SQLCMD -A -E -d {database_name}
  1. 在該數據庫中,嘗試以下操作:
UPDATE sys.objects$ {enter}
SET [name] = N'obsolete' {enter}
WHERE [object_id] = {ye_olde_object_id}; {enter}
GO {enter}

在您輸入GO {enter}.

**直接編輯系統目錄表時請謹慎,不要對這樣做的想法感到太自在。只有在絕對沒有其他方法可以解決問題時才應該這樣做(例如這裡的案例)。**避免直接編輯可能有幾個原因,但最初想到的兩個原因是:

  • 就像我們創建的數據模型一樣,可能有一些我們不知道的事情如何工作的規則和工作流程(例如,非規範化、管理跨各種表的數據狀態的“業務”規則等)
  • 如果您遇到問題並簽訂了支持契約(我沒有看到支持協議的條款,但我很難相信這種語言不會出現在那裡)

@Paul Randal在對我的相關答案的評論中證實:“手動編輯系統表不可撤銷地在數據庫的引導頁面中設置一個標誌,將您的數據庫標記為已以這種方式編輯,並且 CSS 可能決定不提供幫助如果您隨後對該數據庫有問題。”

引用自:https://dba.stackexchange.com/questions/190792