是否可以在不解析源的情况下选择插入,更新或删除记录的所有sproc名称列表?我需要创建一个TSQL实用程序脚本来执行此操作。效率不是问题,因为它每年只运行几次(诅咒者我的意思是光标是可以的)。理想情况下,此脚本不包含对temp或local变量表的更新。
我在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 :(得分: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
)
答案 1 :(得分:1)
这是sys.sql_dependencies的问题。 SQL无法准确地跟踪存储过程中的依赖关系(有合理的原因,它不能,但现在不允许去那里)。这甚至没有考虑动态SQL或CLR程序。
Visual Studio Database Edition具有一些更好的功能,但它可以跟踪scipts中的依赖项,而不是实时数据库中的依赖项。它可以将实时数据库反向工程为脚本并分析生成的脚本,比sys.sql_dependencies更精确。它无法处理动态SQL。
答案 2 :(得分:0)
感谢Cade Roux的回答,我能够非常接近:
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