0

情况是我们有一个 SQL 实例,上面有许多数据库。大多数数据库都有特定的过程。

如果这个过程的主体在所有数据库中都相同,有没有办法用 SQL 检查?

我想这样做,因为有时我需要对某些程序、功能或视图进行“大规模部署”,但在这种情况下,我不确定该程序在创建后是否没有被修改。

4

4 回答 4

1
SELECT * FROM sys.databases 

将为您提供数据库列表。您可以将数据库名称加载到游标中并遍历每个数据库。下一个,

SELECT ROUTINE_NAME, ROUTINE_DEFINITION, * 
FROM DatabaseName.INFORMATION_SCHEMA.ROUTINES

将为您提供存储过程的列表。您可能需要使用动态 SQL 来动态设置来自游标的 DatabaseName 部分。ROUTINE_DEFINITION 列将包含存储过程主体。然后,您可以比较此列以查看它与您的其他数据库等是否相同或不同。

于 2013-07-08T13:35:56.797 回答
0

以下 t-sql 将为您提供现有存储过程的定义。从这里您可以尝试测试定义是否是它们应该是的

select 
    o.name, m.definition 
from 
    sys.objects o
    left join sys.sql_modules m on o.object_id = m.object_id 
where o.type = 'P'

更完整的示例:

set nocount on
declare @spName nvarchar(100) = 'usp'
declare @spDef nvarchar(max) = 'create procedure ....'
declare @spDefInDb nvarchar(max)
declare @nstSql as nvarchar(max)

declare @tdbs table (
    dbName nvarchar(50),
    done bit
)

insert into @tdbs select name, 0 from sys.databases

declare @currentDb nvarchar(50) = null
select @currentDb = dbName from @tdbs where done = 0

while (@currentDb is not null) begin
    --print @currentDb
    set @nstSql = N'select @spDefOut = m.definition from ['+@currentDb+'].sys.objects o left join ['+@currentDb+'].sys.sql_modules m on o.object_id = m.object_id where o.name=@spNameIn and o.type = ''P'''    
    set @spDefInDb = ''
    exec sp_executesql 
        @nstSql,
        N'@spDefOut nvarchar(max) output, @spNameIn nvarchar(100)',
        @spDefOut = @spDefInDb output, @spNameIn = @spName

    if ( @spDefInDb is not null and @spDefInDb != '' ) begin
        print @currentDb
        print @spDefInDb
    end

    update @tdbs set done = 1 where dbName = @currentDb
    set @currentDb = null
    select @currentDb = dbName from @tdbs where done = 0
end
于 2013-07-08T13:31:09.133 回答
0

我曾经做过类似的事情:使用 T-SQL CHECKSUM 函数,我为每个数据库中每个存储过程的主体计算了一个校验和,并将过程名称和校验和存储在一个表中。那么,在两个数据库之间构建一个比较这些表的查询非常容易:如果使用动态 SQL 构建,您可以构建一个自动查询,将每个数据库中的过程与参考数据库进行比较(我为一家提供 ACH 的公司做了这个为许多银行提供功能,并出于安全原因希望维护并行数据库)。

如果您需要有关构建该功能的具体指导,请发表评论,我会尽力满足您的要求。

于 2013-07-08T22:00:29.893 回答
-1

像这样的东西?请注意,我正在使用未记录和不受支持的Sp_MSForEachDB

使用 [某些数据库]

CREATE TABLE spdef(
    dbname sysname, 
    sptext NVARCHAR(MAX))

EXEC Sp_MSForEachDB 'use ?; INSERT INTO [SomeDatabase]..spdef(dbname, sptext) SELECT '' + ? + '', OBJECT_DEFINITION (OBJECT_ID(N''VerifyPortalTab''));'

然后您可以离线进行数据库之间的比较

* 编辑*
遵循@AaronBertrand 的建议,我不想宣传这个答案

于 2013-07-08T13:43:47.263 回答