2009-12-04 46 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 
相关问题