How do I find all stored procedures that insert, update, or delete records?

后端 未结 3 2099
名媛妹妹
名媛妹妹 2020-12-03 19:14

Is it possible, without parsing source, to select a list of all sproc names that insert, update, or delete records? I need to create a TSQL utility script that will do this.

相关标签:
3条回答
  • 2020-12-03 19:49

    Thanks to Cade Roux's answer i was able to get very close with this:

    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].['+@ROUTINE_NAME+'] TO ['+@RoleName +']   '  
    
    
        FETCH NEXT FROM GrantList INTO @ROUTINE_NAME
    END
    CLOSE GrantList
    DEALLOCATE GrantList
    
    0 讨论(0)
  • 2020-12-03 19:50

    That is the problem with sys.sql_dependencies. SQL cannot accurately track dependencies in stored procedures (there are sound reasons why it can't, but lets no go there now). That is without even considering dynamic SQL or CLR procedures.

    Visual Studio Database Edition has some better capabilities, but it can track dependencies in scipts, not in a live database. It can though reverse engineer live databases into scripts and analyse the resulted scripts, to some better accuracy than sys.sql_dependencies can. It cannot handle dynamic SQL.

    0 讨论(0)
  • 2020-12-03 19:59

    Call sp_refreshsqlmodule on all non-schema bound stored procedures:

    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 讨论(0)
提交回复
热议问题