2017-03-02 31 views
0

我通過獲取它們的定義並在其上運行ALTER語句來檢查現有存儲過程的有效性。使用EXEC()重新創建存儲過程沒有發現錯誤

我遇到的問題是,沒有編譯的任何存儲過程(因爲依賴已經消失)沒有被標記爲這樣。

如果我嘗試在SSMS中運行相同的ALTER命令,我會收到錯誤消息。 編輯:不,我不....

DECLARE @def nvarchar(MAX) 
BEGIN TRY 
    -- refresh the stored procedure 
    SELECT @def = REPLACE(definition,'CREATE PROCEDURE ','ALTER PROCEDURE ') 
     FROM sys.sql_modules 
    WHERE ... -- selecting/limiting clause 

    EXEC (@def); 

END TRY 
BEGIN CATCH 
    PRINT 'Validation failed : ' + ERROR_MESSAGE() 
END CATCH 

我有什麼做的陷阱非編譯錯誤?由於

+0

當你改變一個proc到底是什麼錯誤?您可能不應該看到問題,因爲SQL Server在創建特效時會執行延遲名稱解析(至少對於表)。 – DavidG

+0

糟糕!我的錯誤 - SSMS將編譯存儲的procs缺少的依賴關係 - 它只會突出顯示缺少的項目,並帶有一個紅色的波浪線...... – radders

+0

好的,現在投票結束它,因爲它是不可複製的。 – DavidG

回答

2

SQL Server存儲過程使用deferred name resolution

創建存儲過程時,過程中的語句將進行語法準確性分析。如果在過程定義中遇到語法錯誤,則會返回錯誤,並且不會創建存儲過程。如果語句在語法上正確,則存儲過程的文本將存儲在sys.sql_modules目錄視圖中。

當第一次執行存儲過程時,查詢處理器將從sys.sql_modules目錄視圖中讀取存儲過程的文本,並檢查該過程使用的對象的名稱是否存在。此過程稱爲延遲名稱解析,因爲存儲過程引用的表對象不必在創建存儲過程時存在,但只有在執行時才存在。

所以你觀察到的行爲是有意的。你需要的是找出哪些程序依賴於你丟失的表格。爲此,請參閱View the Dependencies of a Stored Procedure,正確答案取決於您的SQL Server版本。 SQL Server 2016以某種方式更好地跟蹤這些信息並提供更好的視圖。在此之前,這個過程非常難以靠得住,請閱讀Keeping sysdepends up to date in SQL Server 2008

0

忘記這一點 - 找錯了樹; - ((

的存儲過程將編譯即使它的依賴也水漲船高OK 在SSMS的編輯器突出了丟失的物品,但不會停止。從工作ALTER語句

這個查詢將確定缺少依賴所有存儲的特效:

-- table variable to store procedure names 
DECLARE @v TABLE (RecID INT IDENTITY(1,1), spname sysname) 

-- retrieve the list of stored procedures 
INSERT INTO @v(spname) 
    SELECT 
     '[' + s.[name] + '].[' + sp.name + ']' 
    FROM sys.procedures sp 
    INNER JOIN sys.schemas s ON s.schema_id = sp.schema_id 
    WHERE is_ms_shipped = 0 
     AND sp.name like 'Get%' 

-- counter variables 
DECLARE @cnt INT, @Tot INT 
SELECT @cnt = 1 
SELECT @Tot = COUNT(*) FROM @v 

DECLARE @spname sysname 
DECLARE @ref nvarchar(MAX) 

-- start the loop 
WHILE @Cnt <= @Tot BEGIN 
    SELECT @spname = spname 
     FROM @v 
     WHERE RecID = @Cnt 

    BEGIN 

     SELECT @ref = referenced_entity_name 
      FROM sys.dm_sql_referenced_entities (@spname, 'OBJECT') 
     WHERE referenced_id IS NULL; 

    END 
    SET @Cnt = @cnt + 1 
END