跨多个数据库比较存储过程(SQL Server)

时间:2010-01-25 16:44:27

标签: sql-server tsql synchronization

SQL Gurus -

我们的架构由多个客户数据库和一个公共代码库组成。当我们部署数据库更改时,必须在每个数据库中运行脚本。

由于部署问题,我们的存储过程有时会彼此不同步。我想创建一个脚本来返回这些匹配的程序,以确保我们在部署后同步数据库副本。

是否可以比较两个或多个数据库,让脚本查看两个数据库之间的所有过程,并返回不匹配的内容?

产生效果:

DATABASE_1 | DATABASE_2  | MISMATCHED_PROCEDURE | DATABASE_1_MODIFY_DATE | DATABASE_2_MODIFY_DATE
Customer_1 | Customer_2  | sp_get_names         | 1/1/2010               | 1/2/2010
Customer_1 | Customer_2  | sp_add_person        | 1/5/2010               | 1/6/2010

作为奖励,是否可以让脚本通过将最新脚本应用于过时脚本来自动同步数据库?

非常感谢!

10 个答案:

答案 0 :(得分:19)

有很多工具可以做到这一点。其中最好的是Red-Gate SQL Compare。另一个非常好的替代方法是使用Visual Studio Database Professional来管理数据库模式。除此之外,它将进行非常好的模式比较。

答案 1 :(得分:11)

如果您没有针对数据库架构师的SQL Compare或Visual Studio团队系统(Data Dude)......请使用此... SQL 2005及以上

select t1.name,t1.modify_date,t2.modify_date
 from Database1.sys.procedures t1
join Database2.sys.procedures t2 on t1.name  = t2.name
and  object_definition(t1.object_id) <>  object_definition(t2.object_id)

答案 2 :(得分:11)

您可以使用下面的脚本识别哪些程序(以及略有修改的其他对象)不同。

要同步数据库,您可能需要尝试ApexSQL Diff。它类似于Red Gate的SQL Compare。

select S1.name [Db1_Schema], O1.name as [Db1_Object], O1.modify_date,
S2.name [Db1_Schema], O2.name as [Db1_Object], O2.modify_date
from database.sys.all_objects O1
inner join database2.sys.all_objects O2 on O1.name = O2.name
inner join database.sys.syscomments C1 on O1.object_id = C1.id
inner join database2.sys.syscomments C2 on O2.object_id = C2.id
inner join database.sys.schemas S1 on O1.schema_id = S1.schema_id
inner join database2.sys.schemas S2 on O2.schema_id = S2.schema_id
where C1.text <> C2.text and
-- remove the line below if you want to search all objects
O1.type = 'P' 

答案 3 :(得分:3)

Red Gate的Sql Compare是完美的解决方案。 但是,如果你付不起它的成本,那么有一个非常好的软件免费:Star Inix的Sql Compare http://www.starinix.com/sqlcompare02.htm

答案 4 :(得分:3)

使用以下内容:

   SELECT DISTINCT
      o1.name AS Object_Name1,
      o1.type_desc as type_desc1,
      o2.name AS Object_Name2,
      o2.type_desc as type_desc2
   FROM DB1.sys.sql_modules m1
   INNER JOIN DB1.sys.objects o1
   ON m1.object_id = o1.object_id
   FULL OUTER JOIN DB2.sys.sql_modules m2
   INNER JOIN DB2.sys.objects o2
   ON m2.object_id = o2.object_id
   ON o1.name = o2.name
   WHERE isnull(m2.definition,'') <> isnull(m1.definition,'')        

答案 5 :(得分:1)

简单的回答,但是在所有程序上删除和创建脚本将非常简单有效。

答案 6 :(得分:1)

这与切向相关,但我写了一些内容,提供了两个存储过程的文本之间的百分比匹配统计信息:http://www.sqlservercentral.com/scripts/T-SQL/65787/

答案 7 :(得分:1)

如果要比较两个数据库中的所有存储过程和另一个中不存在的那些存储过程的输出名称,请使用以下命令。请注意,这不会仅检查存储过程的定义名称,但有一种方法可以检查它。

-- Declare 2 variable names to hold the name of the databases
DECLARE @DB1 varchar(50)
SET @DB1 = 'nameOfDb1'
DECLARE @DB2 varchar(50)
SET @DB2 = 'nameOfDb2'
EXEC('SELECT
        t1.name,
        t2.name
      FROM '
        + @DB1 +'.sys.procedures t1
      FULL OUTER JOIN '
    + @DB2 + '.sys.procedures t2
      on t1.name = t2.name
      where t1.object_id IS NULL
      OR t2.object_id IS NULL')

答案 8 :(得分:1)

是的,RedGate的功能很棒,但这就是我在两个不同数据库中比较存储过程所做的工作: 1 - 将所有存储过程编写到单独的文件中。您可以通过Microsoft SQL Server Management Studio向导执行此操作。 2 - 与我比较的其他数据库中的相同。 3 - 开始KDiff3,我相信是免费的。 4 - 给它需要通过的两个目录。 5 - 现在通过双击看到红色的位置检查结果,下面的面板将告诉您差异。

完成!

答案 9 :(得分:0)

以下过程可以找出两个不同数据库中函数,过程,触发器的不同之处。将数据库名称作为参数传递。

IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.ROUTINES WHERE Specific_name = 'SP_SCRIPTDIFF')

DROP PROCEDURE DBO.SP_SCRIPTDIFF

GO

CREATE PROCEDURE [dbo].SP_SCRIPTDIFF

@DBNAME1 SYSNAME, 
@DBNAME2 SYSNAME

AS

/*
DATE      : 2016/07/29
AUTHOR    : SEENI 
OBJECTIVE : TO COMPARE THE FUNCTIONS, PROCEDURES AND TRIGGERS IN TWO DIFFERENT DATABASES, PASS NAME OF DATABASE1, AND DATABASE2 AS INPUTS.
*/

BEGIN

SET NOCOUNT ON 

Exec ('select  DISTINCT O1.name as [ObjectName], O1.modify_date As DateIn_'+@DBNAME1+',  O2.modify_date As DateIn_'+@DBNAME2+',o1.type as Type from '+
@DBNAME1+'.sys.all_objects O1 join '+ @DBNAME2+'.sys.all_objects O2 on O1.name = O2.name and  O1.type = O2.type join '+
@DBNAME1+'.sys.syscomments C1 on O1.object_id = C1.id join '+ @DBNAME2+'.sys.syscomments C2 on O2.object_id = C2.id join '+
@DBNAME1+'.sys.schemas S1 on O1.schema_id = S1.schema_id join '+ @DBNAME2+'.sys.schemas S2 on O2.schema_id = S2.schema_id
where C1.text <> C2.text and c1.colid = c2.colid  and O1.Type in (''FN'',''P'',''T'') And o1.Is_Ms_Shipped = 0  Order by O1.type,ObjectName')

RETURN

END 

GO