2009-12-04 74 views
5

是否有可能在不解析源代碼的情況下選擇插入,更新或刪除記錄的所有sproc名稱列表?我需要創建一個TSQL實用程序腳本來執行此操作。效率不是問題,因爲它每年只運行幾次(Curse'rs我的意思是遊標可以)。理想情況下,這個腳本不會包含對臨時或局部變量表的更新。如何查找插入,更新或刪除記錄的所有存儲過程?

我試過在SO Question上找到以下查詢。

SELECT 
so.name, 
so2.name, 
sd.is_updated 
from sysobjects so 
inner join sys.sql_dependencies sd on so.id = sd.object_id 
inner join sysobjects so2 on sd.referenced_major_id = so2.id 
where so.xtype = 'p' -- procedure 
and 
is_updated = 1 -- proc updates table, or at least, I think that's what this means 

但它會產生假陰性。

+0

您所提供的鏈接包括了答案對於這個問題......只需要添加刪除即可。 – 2009-12-04 22:28:02

+0

即使只更新sprocs,我仍然會得到約5%的失敗率。 – 2009-12-04 22:33:26

回答

6

所有非架構呼叫sp_refreshsqlmodule約束存儲過程:

DECLARE @template AS varchar(max) 
SET @template = 'PRINT ''{OBJECT_NAME}'' 
EXEC sp_refreshsqlmodule ''{OBJECT_NAME}'' 

' 

DECLARE @sql AS varchar(max) 

SELECT @sql = ISNULL(@sql, '') + REPLACE(@template, '{OBJECT_NAME}', 
              QUOTENAME(ROUTINE_SCHEMA) + '.' 
              + QUOTENAME(ROUTINE_NAME)) 
FROM INFORMATION_SCHEMA.ROUTINES 
WHERE OBJECTPROPERTY(OBJECT_ID(QUOTENAME(ROUTINE_SCHEMA) + '.' 
           + QUOTENAME(ROUTINE_NAME)), 
         N'IsSchemaBound') IS NULL 
     OR OBJECTPROPERTY(OBJECT_ID(QUOTENAME(ROUTINE_SCHEMA) + '.' 
            + QUOTENAME(ROUTINE_NAME)), 
          N'IsSchemaBound') = 0 

     EXEC (
       @sql 
      ) 
+0

謝謝運行,讓我更接近。還有一些假陰性但只有少數。我能夠使用我的原始代碼和您的代碼足夠接近。我發佈了我的代碼作爲答案。 – 2009-12-05 00:50:44

+0

您是否發現任何因爲潛在變更而失效的SP?這總是很有趣;-) – 2009-12-05 02:30:25

1

這是sys.sql_dependencies的問題。 SQL不能準確地跟蹤存儲過程中的依賴關係(有充分的理由說明爲什麼它不行,但現在不要去那裏)。這甚至沒有考慮動態SQL或CLR程序。

Visual Studio Database Edition具有一些更好的功能,但它可以跟蹤scipts中的依賴關係,而不是在活動數據庫中。它可以通過反向工程將實時數據庫轉換爲腳本並分析結果腳本,以獲得比sys.sql_dependencies更高的準確性。它無法處理動態SQL。

0

得益於凱德魯的回答我是能夠得到非常接近這一點:

DECLARE @RoleName nvarchar(255) 
SET @RoleName = 'READONLYUSER' 

DECLARE @ROUTINE_NAME nvarchar(255) 
DECLARE RoutineList Cursor FOR 
SELECT ROUTINE_NAME 
FROM INFORMATION_SCHEMA.ROUTINES 
WHERE (OBJECTPROPERTY(OBJECT_ID(QUOTENAME(ROUTINE_SCHEMA) + '.' + QUOTENAME(ROUTINE_NAME)), N'IsSchemaBound') IS NULL OR OBJECTPROPERTY(OBJECT_ID(QUOTENAME(ROUTINE_SCHEMA) + '.' + QUOTENAME(ROUTINE_NAME)), N'IsSchemaBound') = 0) 
    AND NOT ROUTINE_NAME like 'sel%' 
    AND NOT ROUTINE_NAME like 'sp_upd%' 
    AND NOT ROUTINE_NAME like 'sp_sel%' 
    AND NOT ROUTINE_NAME like 'sp_ins%' 
OPEN RoutineList 
FETCH NEXT FROM RoutineList 
INTO @ROUTINE_NAME 
WHILE @@FETCH_STATUS = 0 
BEGIN 

    EXEC ('EXEC sp_refreshsqlmodule ''' + @ROUTINE_NAME + '''') 

    FETCH NEXT FROM RoutineList INTO @ROUTINE_NAME 
END 
CLOSE RoutineList 
DEALLOCATE RoutineList 


DECLARE GrantList Cursor FOR 
SELECT DISTINCT 
    so.name AS ROUTINE_NAME 
FROM sysobjects so 
LEFT JOIN (
    SELECT 
     so.name, 
     so2.name AS [table], 
     sd.is_updated 
     FROM sysobjects so 
     INNER JOIN sys.sql_dependencies sd ON so.id = sd.object_id 
     INNER JOIN sysobjects so2 ON sd.referenced_major_id = so2.id 
     WHERE so.xtype = 'p' 
     and is_updated = 1 
) Updates ON so.name = Updates.name 
WHERE 
    so.xtype = 'p' -- procedure 
    AND Updates.name is null 
    AND so.name NOT LIKE '%[_]%' 
ORDER BY so.name 

OPEN GrantList 
FETCH NEXT FROM GrantList 
INTO @ROUTINE_NAME 
WHILE @@FETCH_STATUS = 0 
BEGIN 

    print 'GRANT EXECUTE ON [dbo].['[email protected]_NAME+'] TO ['[email protected] +'] ' 


    FETCH NEXT FROM GrantList INTO @ROUTINE_NAME 
END 
CLOSE GrantList 
DEALLOCATE GrantList 
相關問題