T-Sql

有什麼方法可以使儲存過程程式碼動態引用其他數據庫,而無需動態 sql?

  • September 12, 2018

我有兩個數據庫的情況:

  • ABC數據
  • ABC使用者

ABCData 中的儲存過程之一需要對 ABCUsers 中的表執行插入操作。這可能只是硬編碼:

INSERT ABCUsers.dbo.Table1 VALUES('a');

但是我們遇到的下一個問題是,我們希望將這些數據庫對備份並重新部署到類似名稱的其他數據庫中,以用於測試和開發目的:

  • XYZ數據
  • XYZ使用者

這意味著 XYZData 數據庫將包含一個不起作用的儲存過程 - 因為插入具有硬編碼ABCUsers.dbo.Table1,我們不想更改它

我們可以在 sproc 中找出目前數據庫名稱,調整它並動態執行 sql:

DECLARE @DataDbName sysname = (DB_NAME());
DECLARE @UserDBName NVARCHAR(20) = (SELECT REPLACE(@DataDbName, 'Data', 'Users'));
EXEC CONCAT('INSERT ', @UserDbName, '.dbo.Table1 VALUES(''a'');')

但我認為這樣做的前景實際上讓我感到身體不適;)(尤其是因為這是一個大規模簡化的範例,其中有數十個儲存過程,每個儲存過程都對其他數據庫進行數十次呼叫)

有沒有辦法在創建過程中為數據庫名稱取別名,所以 sproc 總是可以這樣說:

INSERT UserDbAlias.dbo.Table1 VALUES('a');

而當ABCUsers數據庫被創建時,UserDbAlias -> ABCUsers但是當XYZUsers數據庫被創建時UserDbAlias -> XYZUsers


或者,這是一個 git/tfs 原始碼控制 - 有沒有辦法編寫 sproc 的原始碼控製版本,以便在部署時對其進行動態修改,並且原始原始碼可以包含某種佔位符用於 db 名稱,但是它們在部署時被實際硬編碼的不同數據庫名稱替換(自動)


腳註:我查看了A way to reference other DB without hardcoding its name這似乎描述了我的問題,但沒有答案。該問題提到“我已經查看了同義詞,但它們不適用於 EF6..”(釋義)

同義詞對我有用嗎?我們使用 EF6,但我不確定實際問題是什麼,為什麼它不能解決。我們在 db 中的 sproc 名稱永遠不會改變,我們不需要為 sproc 本身起別名,它是我們需要別名的插入表名稱。Sproc1如果無論它是否在ABCDataor中都始終呼叫 sproc XYZData,並且同義詞解析發生在 sproc 內部,那麼 EF6 甚至會有問題嗎?

除了評論中提出的設計考慮之外,…

在創建儲存過程之前考慮一級間接:

  • 為儲存過程編寫一個模板,為模式名稱使用標記佔位符

INSERT DBNAMETOKEN.dbo.Table1 VALUES('a');

  • 編寫一個預部署腳本(sed?),專門為每個模式創建一個新文件,用實際的模式名稱代替令牌。
  • 將生成的腳本放在每個模式的部署目錄中,它們可以照常安裝。

好處

  • 很好地擴展
  • 模板和自定義版本都可能受版本控制
  • 更新/修復仍然可以通過對模板文件的單個更改進行部署,並通過建構步驟傳播
  • 可能更容易根據情況安排/跟踪每個模式的更新部署
  • 將儲存過程簡化為一組簡單的(r)SQL,專注於手頭的任務,而不是讓它跨不同模式工作的動態。

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