Sql-Server

有沒有辦法強制將過程的 模式繼承到其中呼叫的所有過程

  • May 7, 2020

如果我有一個儲存過程schema1.proc1並且它選擇 from table1,它會正確選擇 from schema1.table1。但是,當schema1.proc1執行時proc2,它會嘗試查找並執行dbo.proc2

沒有dbo.proc2,所以它返回一個錯誤,即未找到儲存過程。schema1.proc2即使sys.sysdepends連結schema1.proc1schema1.proc2. _ 但是,也有一個schema2.proc2,但返回的錯誤只是proc2沒有找到或不存在。

除了讓該使用者default schema = schema1讓儲存過程從其自己的模式中執行該過程(即假設schema1.proc2應該在搜尋之前執行dbo.proc2)之外,還有其他方法嗎?

我知道我們可以簡單地proc2schema1顯式開頭,但我們試圖避免必須在儲存過程中找到所有儲存過程呼叫,以將呼叫過程的模式前綴附加到被呼叫的過程。

我可以從中看到sys.sysdepends它正確連結proc1到正確的數據庫對象proc2,該對像也與 相關聯schema1,但由於某種原因,它似乎並沒有尋找那個proc2,而是尋找dbo.proc2.

請讓我知道是否有一些我只是缺少告訴編譯器首先檢查的數據庫級別設置。

老實說,正確的做法是修復程式碼模式指定應始終是明確的。您可以同時使用同義詞來掩蓋問題並為您爭取時間:

CREATE SYNONYM dbo.proc2 FOR schema1.proc2;

但是,如果您在數據庫中有兩個過程,並且它們都說 ,那將無濟於事schema1.proc1schema2.proc2因為EXEC proc2它們都將遵循同義詞的路徑。

我強烈建議的另一件事是不要將模式用作儲存具有完全相同名稱的**不同對象的分區。我可以在開發環境中看到目的,您希望輕鬆切換模式以針對 QA 或測試模式測試您的程式碼,但這應該是批發的,並且不應該同時有效- 一種更好方法具有這種類型的獨立性將是數據庫而不是模式(恕我直言)。schema1.Employees``schema2.Employees

在沒有架構引用的情況下找到引用其他儲存過程的所有儲存過程不應該是“非常麻煩的事情”

您可以輕鬆找到所有沒有架構引用的對象:

SELECT CallerSchema = caller_sch.name, CallerName = callers.name,
 dep.referenced_entity_name, caller_mod.definition
FROM sys.sql_expression_dependencies AS dep
 INNER JOIN sys.procedures AS callers
 ON callers.[object_id] = dep.[referencing_id]
 INNER JOIN sys.schemas AS caller_sch
 ON callers.schema_id = caller_sch.schema_id
 INNER JOIN sys.sql_modules AS caller_mod
 ON callers.[object_id] = caller_mod.[object_id]
WHERE dep.referenced_schema_name IS NULL;

您也可以通過蠻力解析來做到這一點,儘管這有點模糊,並假設您的模式名稱不夠常見而不會導致誤報(並且該模式沒有在任何地方引用- 坦率地說,上面更可靠):

SELECT CallerName = callers.name, CallerSchema = caller_sch.name,
   CalleeName = callees.name, CalleeSchema = callee_sch.name, 
   Definition = caller_mod.definition
FROM sys.sql_dependencies AS dep
 INNER JOIN sys.procedures AS callers
 ON callers.[object_id] = dep.[object_id]
 INNER JOIN sys.schemas AS caller_sch
 ON callers.schema_id = caller_sch.schema_id
 INNER JOIN sys.procedures AS callees
 ON callees.[object_id] = dep.referenced_major_id
 INNER JOIN sys.schemas AS callee_sch
 ON callees.schema_id = callee_sch.schema_id
 INNER JOIN sys.sql_modules AS caller_mod
 ON callers.[object_id] = caller_mod.[object_id]
WHERE caller_mod.definition NOT LIKE N'%' + callee_sch.name + N'%';

另外sysdepends(你不應該再使用它了,有更現代的視圖)只是報告依賴關係。它不規定優化器訪問路徑。

我不相信有任何方法可以做你所要求的。在您開始使用模式時,您應該始終在命名中包含模式前綴。這是一種最佳實踐,有助於避免您所描述的問題。SQL Server 允許您在不指定架構的情況下引用對象的唯一原因是它是遺留功能。最初 SQL Server 沒有架構的概念,因此所有內容實際上都在同一個中。

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