情况是我们有一个 SQL 实例,上面有许多数据库。大多数数据库都有特定的过程。
如果这个过程的主体在所有数据库中都相同,有没有办法用 SQL 检查?
我想这样做,因为有时我需要对某些程序、功能或视图进行“大规模部署”,但在这种情况下,我不确定该程序在创建后是否没有被修改。
情况是我们有一个 SQL 实例,上面有许多数据库。大多数数据库都有特定的过程。
如果这个过程的主体在所有数据库中都相同,有没有办法用 SQL 检查?
我想这样做,因为有时我需要对某些程序、功能或视图进行“大规模部署”,但在这种情况下,我不确定该程序在创建后是否没有被修改。
SELECT * FROM sys.databases
将为您提供数据库列表。您可以将数据库名称加载到游标中并遍历每个数据库。下一个,
SELECT ROUTINE_NAME, ROUTINE_DEFINITION, *
FROM DatabaseName.INFORMATION_SCHEMA.ROUTINES
将为您提供存储过程的列表。您可能需要使用动态 SQL 来动态设置来自游标的 DatabaseName 部分。ROUTINE_DEFINITION 列将包含存储过程主体。然后,您可以比较此列以查看它与您的其他数据库等是否相同或不同。
以下 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
我曾经做过类似的事情:使用 T-SQL CHECKSUM 函数,我为每个数据库中每个存储过程的主体计算了一个校验和,并将过程名称和校验和存储在一个表中。那么,在两个数据库之间构建一个比较这些表的查询非常容易:如果使用动态 SQL 构建,您可以构建一个自动查询,将每个数据库中的过程与参考数据库进行比较(我为一家提供 ACH 的公司做了这个为许多银行提供功能,并出于安全原因希望维护并行数据库)。
如果您需要有关构建该功能的具体指导,请发表评论,我会尽力满足您的要求。
像这样的东西?请注意,我正在使用未记录和不受支持的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 的建议,我不想宣传这个答案