Sql server 如何查找插入、更新或删除记录的所有存储过程?

Sql server 如何查找插入、更新或删除记录的所有存储过程?,sql-server,tsql,Sql Server,Tsql,在不分析源的情况下,是否可以选择所有插入、更新或删除记录的存储过程名称的列表?我需要创建一个TSQL实用程序脚本来实现这一点。效率不是一个问题,因为它一年只运行几次(我的意思是说游标可以)。理想情况下,此脚本不包括对临时或局部变量表的更新 我尝试了在上找到的以下查询 但是它会产生错误的否定。这就是sys.sql\u依赖项的问题。SQL不能准确地跟踪存储过程中的依赖关系(有充分的理由说明为什么它不能,但现在就不要这样做了)。这甚至没有考虑动态SQL或CLR过程 VisualStudioDataba

在不分析源的情况下,是否可以选择所有插入、更新或删除记录的存储过程名称的列表?我需要创建一个TSQL实用程序脚本来实现这一点。效率不是一个问题,因为它一年只运行几次(我的意思是说游标可以)。理想情况下,此脚本不包括对临时或局部变量表的更新

我尝试了在上找到的以下查询


但是它会产生错误的否定。

这就是sys.sql\u依赖项的问题。SQL不能准确地跟踪存储过程中的依赖关系(有充分的理由说明为什么它不能,但现在就不要这样做了)。这甚至没有考虑动态SQL或CLR过程

VisualStudioDatabaseEdition有一些更好的功能,但它可以跟踪scipts中的依赖项,而不是实时数据库中的依赖项。它可以将实时数据库反向工程为脚本并分析生成的脚本,其精确度比sys.sql\u依赖项更高。它无法处理动态SQL。

调用所有非架构绑定存储过程:

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
            )

多亏了凯德·鲁克斯的回答,我能够非常接近这一点:

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

您提供的链接包括此问题的答案。。。只需要添加删除。即使只更新存储过程,我的错误率仍在5%左右。感谢运行此功能,我离此更近了。仍然有一些错误的否定,但只有少数。我可以使用我的原始代码和你的代码来接近你。我发布了我的代码作为答案。您是否发现任何SP由于潜在更改而变得无效?那总是很有趣;-)
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