【问题标题】:sql server 2008 database merging with another databasesql server 2008 数据库与另一个数据库合并
【发布时间】:2011-01-22 11:36:51
【问题描述】:

我在两个不同的远程服务器上有 2 个 sql server 数据库。在第一天,他们都完全一样。但随着时间的推移,两者都会发生变化(不同的表、存储过程、视图等)。

如何将它们合并在一起,以便我再次拥有一个 - 两个地方都使用相同的数据库?

【问题讨论】:

    标签: sql sql-server database merge


    【解决方案1】:

    我会看Red Gates SQL Compare,如果它是一个大模式,它非常有用。

    【讨论】:

      【解决方案2】:

      使用此脚本,您可以比较两个数据库:

      USE Master
      GO
      IF EXISTS (SELECT * FROM sysobjects WHERE name = 'sp_CompareDB' and type = 'P')
      DROP PROC sp_CompareDB
      GO
      --------------------------------------------------------------------------------------------
      -- sp_CompareDB
      -- 
      -- The SP compares structures and data in 2 databases.
      -- 1. Compares if all tables in one database have analog (by name) in second database
      -- Tables not existing in one of databases won't be used for data comparing
      -- 2. Compares if structures for tables with the same names are the same. Shows structural
      -- differences like:
      -- authors
      -- Column Phone: in db1 - char(12), in db2 - char(14)
      -- sales
      -- Column Location not in db2
      -- Tables, having different structures, won't be used for data comparing. However if the tables
      -- contain columns of the same type and different length (like Phone in the example above) or
      -- tables have compatible data types (have the same type in syscolumns - char and nchar, 
      -- varchar and nvarchar etc) they will be allowed for data comparing.
      -- 3. Data comparison itself. 
      -- 3.1 Get information about unique keys in the tables. If there are unique keys then one of them
      -- (PK is a highest priority candidate for this role) will be used to specify rows with
      -- different data.
      -- 3.2 Get information about all data columns in the table and form predicates that will be 
      -- used to compare data.
      -- 3.3 Compare data with the criteria:
      -- a. if some unique keys from the table from first database do not exist in second db (only
      -- for tables with a unique key)
      -- b. if some unique keys from the table from second database do not exist in first db (only
      -- for tables with a unique key)
      -- c. if there are rows with the same values of unique keys and different data in other
      -- columns (only for tables with a unique key)
      -- d. if there are rows in the table from first database that don't have a twin in the 
      -- table from second db
      -- e. if there are rows in the table from second database that don't have a twin in the 
      -- table from first db
      --------------------------------------------------------------------------------------------
      -- Parameters:
      -- 1. @db1 - name of first database to compare
      -- 2. @db2 - name of second database to compare
      -- 3. @TabList - list of tables to compare. if empty - all tables in the databases should be
      -- compared
      -- 4. @NumbToShow - number of rows with differences to show. Default - 10.
      -- 5. @OnlyStructure - flag, if set to 1, allows to avoid data comparing. Only structures should
      -- be compared. Default - 0
      -- 6. @NoTimestamp - flag, if set to 1, allows to avoid comparing of columns of timestamp
      -- data type. Default - 0
      -- 7. @VerboseLevel - if set to 1 allows to print querues used for data comparison
      --------------------------------------------------------------------------------------------
      -- Created by Viktor Gorodnichenko (c)
      -- Created on: July 5, 2001
      -- 060327 nbn: Changed 'Colimn' into 'column' & added "order by" to table listings.
      --------------------------------------------------------------------------------------------
      CREATE PROC sp_CompareDB
      @db1 varchar(128),
      @db2 varchar(128),
      @OnlyStructure bit = 0,
      @TabList varchar(8000) = '',
      @NumbToShow int = 10,
      @NoTimestamp bit = 0,
      @VerboseLevel tinyint = 0
      AS
      if @OnlyStructure <> 0
      set @OnlyStructure = 1
      if @NoTimestamp <> 0
      set @NoTimestamp = 1
      if @VerboseLevel <> 0
      set @VerboseLevel = 1
      
      SET NOCOUNT ON
      SET ANSI_WARNINGS ON
      SET ANSI_NULLS ON
      declare @sqlStr varchar(8000)
      set nocount on
      -- Checking if there are specified databases
      declare @SrvName sysname
      declare @DBName sysname
      set @db1 = RTRIM(LTRIM(@db1))
      set @db2 = RTRIM(LTRIM(@db2))
      set @SrvName = @@SERVERNAME
      if CHARINDEX('.',@db1) > 0
      begin
      set @SrvName = LEFT(@db1,CHARINDEX('.',@db1)-1)
      if not exists (select * from master.dbo.sysservers where srvname = @SrvName)
      begin
      print 'There is no linked server named '+@SrvName+'. End of work.'
      return 
      end
      set @DBName = RIGHT(@db1,LEN(@db1)-CHARINDEX('.',@db1))
      end
      else
      set @DBName = @db1
      exec ('declare @Name sysname select @Name=name from ['+@SrvName+'].master.dbo.sysdatabases where name = '''+@DBName+'''')
      if @@rowcount = 0
      begin
      print 'There is no database named '+@db1+'. End of work.'
      return 
      end
      set @SrvName = @@SERVERNAME
      if CHARINDEX('.',@db2) > 0
      begin
      set @SrvName = LEFT(@db2,CHARINDEX('.',@db2)-1)
      if not exists (select * from master.dbo.sysservers where srvname = @SrvName)
      begin
      print 'There is no linked server named '+@SrvName+'. End of work.'
      return 
      end
      set @DBName = RIGHT(@db2,LEN(@db2)-CHARINDEX('.',@db2))
      end
      else
      set @DBName = @db2
      exec ('declare @Name sysname select @Name=name from ['+@SrvName+'].master.dbo.sysdatabases where name = '''+@DBName+'''')
      if @@rowcount = 0
      begin
      print 'There is no database named '+@db2+'. End of work.'
      return 
      end
      
      print Replicate('-',LEN(@db1)+LEN(@db2)+25)
      print 'Comparing databases '+@db1+' and '+@db2
      print Replicate('-',LEN(@db1)+LEN(@db2)+25)
      print 'Options specified:'
      print ' Compare only structures: '+CASE WHEN @OnlyStructure = 0 THEN 'No' ELSE 'Yes' END
      print ' List of tables to compare: '+CASE WHEN LEN(@TabList) = 0 THEN ' All tables' ELSE @TabList END
      print ' Max number of different rows in each table to show: '+LTRIM(STR(@NumbToShow))
      print ' Compare timestamp columns: '+CASE WHEN @NoTimestamp = 0 THEN 'No' ELSE 'Yes' END
      print ' Verbose level: '+CASE WHEN @VerboseLevel = 0 THEN 'Low' ELSE 'High' END
      
      -----------------------------------------------------------------------------------------
      -- Comparing structures
      -----------------------------------------------------------------------------------------
      print CHAR(10)+Replicate('-',36)
      print 'Comparing structure of the databases'
      print Replicate('-',36)
      if exists (select * from tempdb.dbo.sysobjects where name like '#TabToCheck%')
      drop table #TabToCheck
      create table #TabToCheck (name sysname)
      declare @NextCommaPos int
      if len(@TabList) > 0 
      begin
      while 1=1
      begin
      set @NextCommaPos = CHARINDEX(',',@TabList)
      if @NextCommaPos = 0
      begin
      set @sqlstr = 'insert into #TabToCheck values('''+@TabList+''')'
      exec (@sqlstr)
      break
      end
      set @sqlstr = 'insert into #TabToCheck values('''+LEFT(@TabList,@NextCommaPos-1)+''')'
      exec (@sqlstr)
      set @TabList = RIGHT(@TabList,LEN(@TabList)-@NextCommaPos)
      end
      end
      else -- then will check all tables
      begin
      exec ('insert into #TabToCheck select name from '+@db1+'.dbo.sysobjects where type = ''U''')
      exec ('insert into #TabToCheck select name from '+@db2+'.dbo.sysobjects where type = ''U''')
      end
      -- First check if at least one table specified in @TabList exists in db1
      exec ('declare @Name sysname select @Name=name from '+@db1+'.dbo.sysobjects where name in (select * from #TabToCheck)')
      if @@rowcount = 0
      begin
      print 'No tables in '+@db1+' to check. End of work.'
      return
      end
      -- Check if tables existing in db1 are in db2 (all tables or specified in @TabList)
      if exists (select * from tempdb.dbo.sysobjects where name like '#TabNotInDB2%')
      drop table #TabNotInDB2
      create table #TabNotInDB2 (name sysname)
      insert into #TabNotInDB2 
      -- 060327 nbn: Added order by..
      exec ('select name from '+@db1+'.dbo.sysobjects d1o '+
      'where name in (select * from #TabToCheck) and '+
      ' d1o.type = ''U'' and not exists '+
      '(select * from '+@db2+'.dbo.sysobjects d2o'+
      ' where d2o.type = ''U'' and d2o.name = d1o.name) order by name')
      if @@rowcount > 0
      begin
      print CHAR(10)+'The table(s) exist in '+@db1+', but do not exist in '+@db2+':'
      select * from #TabNotInDB2 
      end
      delete from #TabToCheck where name in (select * from #TabNotInDB2)
      drop table #TabNotInDB2
      
      if exists (select * from tempdb.dbo.sysobjects where name like '#TabNotInDB1%')
      drop table #TabNotInDB1
      create table #TabNotInDB1 (name sysname)
      insert into #TabNotInDB1 
      -- 060327 nbn: Added order by..
      exec ('select name from '+@db2+'.dbo.sysobjects d1o '+
      'where name in (select * from #TabToCheck) and '+
      ' d1o.type = ''U'' and not exists '+
      '(select * from '+@db1+'.dbo.sysobjects d2o'+
      ' where d2o.type = ''U'' and d2o.name = d1o.name) order by name')
      if @@rowcount > 0
      begin
      print CHAR(10)+'The table(s) exist in '+@db2+', but do not exist in '+@db1+':'
      select * from #TabNotInDB1 
      end
      delete from #TabToCheck where name in (select * from #TabNotInDB1)
      drop table #TabNotInDB1
      -- Comparing structures of tables existing in both dbs
      print CHAR(10)+'Checking if there are tables existing in both databases having structural differences ...'+CHAR(10)
      if exists (select * from tempdb.dbo.sysobjects where name like '#DiffStructure%')
      drop table #DiffStructure
      create table #DiffStructure (name sysname)
      set @sqlStr='
      declare @TName1 sysname, @TName2 sysname, @CName1 sysname, @CName2 sysname,
      @TypeName1 sysname, @TypeName2 sysname,
      @CLen1 smallint, @CLen2 smallint, @Type1 sysname, @Type2 sysname, @PrevTName sysname
      declare @DiffStructure bit
      declare Diff cursor fast_forward for
      select d1o.name, d2o.name, d1c.name, d2c.name, d1t.name, d2t.name,
      d1c.length, d2c.length, d1c.type, d2c.type
      from ('+@db1+'.dbo.sysobjects d1o 
      JOIN '+@db2+'.dbo.sysobjects d2o2 ON d1o.name = d2o2.name and d1o.type = ''U'' --only tables in both dbs
      and d1o.name in (select * from #TabToCheck)
      JOIN '+@db1+'.dbo.syscolumns d1c ON d1o.id = d1c.id
      JOIN '+@db1+'.dbo.systypes d1t ON d1c.xusertype = d1t.xusertype)
      FULL JOIN ('+@db2+'.dbo.sysobjects d2o 
      JOIN '+@db1+'.dbo.sysobjects d1o2 ON d1o2.name = d2o.name and d2o.type = ''U'' --only tables in both dbs
      and d2o.name in (select * from #TabToCheck)
      JOIN '+@db2+'.dbo.syscolumns d2c ON d2c.id = d2o.id
      JOIN '+@db2+'.dbo.systypes d2t ON d2c.xusertype = d2t.xusertype)
      ON d1o.name = d2o.name and d1c.name = d2c.name
      WHERE (not exists 
      (select * from '+@db2+'.dbo.sysobjects d2o2
      JOIN '+@db2+'.dbo.syscolumns d2c2 ON d2o2.id = d2c2.id
      JOIN '+@db2+'.dbo.systypes d2t2 ON d2c2.xusertype = d2t2.xusertype
      where d2o2.type = ''U''
      and d2o2.name = d1o.name 
      and d2c2.name = d1c.name 
      and d2t2.name = d1t.name
      and d2c2.length = d1c.length)
      OR not exists 
      (select * from '+@db1+'.dbo.sysobjects d1o2
      JOIN '+@db1+'.dbo.syscolumns d1c2 ON d1o2.id = d1c2.id
      JOIN '+@db1+'.dbo.systypes d1t2 ON d1c2.xusertype = d1t2.xusertype
      where d1o2.type = ''U''
      and d1o2.name = d2o.name 
      and d1c2.name = d2c.name 
      and d1t2.name = d2t.name
      and d1c2.length = d2c.length))
      order by coalesce(d1o.name,d2o.name), d1c.name
      open Diff
      fetch next from Diff into @TName1, @TName2, @CName1, @CName2, @TypeName1, @TypeName2,
      @CLen1, @CLen2, @Type1, @Type2
      set @PrevTName = ''''
      set @DiffStructure = 0
      while @@fetch_status = 0
      begin
      if Coalesce(@TName1,@TName2) <> @PrevTName
      begin
      if @PrevTName <> '''' and @DiffStructure = 1
      begin
      insert into #DiffStructure values (@PrevTName)
      set @DiffStructure = 0
      end
      set @PrevTName = Coalesce(@TName1,@TName2)
      print @PrevTName
      end
      if @CName2 is null
      print '' Column ''+RTRIM(@CName1)+'' not in '+@db2+'''
      else
      if @CName1 is null
      print '' Column ''+RTRIM(@CName2)+'' not in '+@db1+'''
      else
      if @TypeName1 <> @TypeName2
      print '' Column ''+RTRIM(@CName1)+'': in '+@db1+' - ''+RTRIM(@TypeName1)+'', in '+@db2+' - ''+RTRIM(@TypeName2)
      else --the columns are not null(are in both dbs) and types are equal,then length are diff
      print '' Column ''+RTRIM(@CName1)+'': in '+@db1+' - ''+RTRIM(@TypeName1)+''(''+
      LTRIM(STR(CASE when @TypeName1=''nChar'' or @TypeName1 = ''nVarChar'' then @CLen1/2 else @CLen1 end))+
      ''), in '+@db2+' - ''+RTRIM(@TypeName2)+''(''+
      LTRIM(STR(CASE when @TypeName1=''nChar'' or @TypeName1 = ''nVarChar'' then @CLen2/2 else @CLen2 end))+'')''
      if @Type1 = @Type2
      set @DiffStructure=@DiffStructure -- Do nothing. Cannot invert predicate
      else
      set @DiffStructure = 1
      fetch next from Diff into @TName1, @TName2, @CName1, @CName2, @TypeName1, @TypeName2,
      @CLen1, @CLen2, @Type1, @Type2
      end
      deallocate Diff
      if @DiffStructure = 1
      insert into #DiffStructure values (@PrevTName)
      '
      exec (@sqlStr)
      if (select count(*) from #DiffStructure) > 0
      begin
      print CHAR(10)+'The table(s) have the same name and different structure in the databases:'
      select distinct * from #DiffStructure 
      delete from #TabToCheck where name in (select * from #DiffStructure)
      end
      else
      print CHAR(10)+'There are no tables with the same name and structural differences in the databases'+CHAR(10)+CHAR(10)
      if @OnlyStructure = 1
      begin
      print 'The option ''Only compare structures'' was specified. End of work.'
      return
      end
      exec ('declare @Name sysname select @Name=d1o.name
      from '+@db1+'.dbo.sysobjects d1o, '+@db2+'.dbo.sysobjects d2o 
      where d1o.name = d2o.name and d1o.type = ''U'' and d2o.type = ''U''
      and d1o.name not in (''dtproperties'') 
      and d1o.name in (select * from #TabToCheck)')
      if @@rowcount = 0
      begin
      print 'There are no tables with the same name and structure in the databases to compare. End of work.'
      return
      end
      
      
      -----------------------------------------------------------------------------------------
      -- Comparing data 
      -----------------------------------------------------------------------------------------
      -- ##CompareStr - will be used to pass comparing strings into dynamic script
      -- to execute the string
      if exists (select * from tempdb.dbo.sysobjects where name like '##CompareStr%')
      drop table ##CompareStr
      create table ##CompareStr (Ind int, CompareStr varchar(8000))
      
      if exists (select * from tempdb.dbo.sysobjects where name like '#DiffTables%')
      drop table #DiffTables
      create table #DiffTables (Name sysname)
      if exists (select * from tempdb.dbo.sysobjects where name like '#IdenticalTables%')
      drop table #IdenticalTables
      create table #IdenticalTables (Name sysname)
      if exists (select * from tempdb.dbo.sysobjects where name like '#EmptyTables%')
      drop table #EmptyTables
      create table #EmptyTables (Name sysname)
      if exists (select * from tempdb.dbo.sysobjects where name like '#NoPKTables%')
      drop table #NoPKTables
      create table #NoPKTables (Name sysname)
      
      if exists (select * from tempdb.dbo.sysobjects where name like '#IndList1%')
      truncate table #IndList1
      else 
      create table #IndList1 (IndId int, IndStatus int,
      KeyAndStr varchar(7000), KeyCommaStr varchar(1000))
      if exists (select * from tempdb.dbo.sysobjects where name like '#IndList2%')
      truncate table #IndList2
      else
      create table #IndList2 (IndId smallint, IndStatus int,
      KeyAndStr varchar(7000), KeyCommaStr varchar(1000))
      
      print Replicate('-',51)
      print 'Comparing data in tables with indentical structure:'
      print Replicate('-',51)
      --------------------------------------------------------------------------------------------
      -- Cursor for all tables in dbs (or for all specified tables if parameter @TabList is passed)
      --------------------------------------------------------------------------------------------
      declare @SqlStrGetListOfKeys1 varchar(8000)
      declare @SqlStrGetListOfKeys2 varchar(8000)
      declare @SqlStrGetListOfColumns varchar(8000)
      declare @SqlStrCompareUKeyTables varchar(8000)
      declare @SqlStrCompareNonUKeyTables varchar(8000)
      set @SqlStrGetListOfKeys1 = '
      declare @sqlStr varchar(8000)
      declare @ExecSqlStr varchar(8000)
      declare @PrintSqlStr varchar(8000)
      declare @Tab varchar(128)
      declare @d1User varchar(128)
      declare @d2User varchar(128)
      declare @KeyAndStr varchar(8000) 
      declare @KeyCommaStr varchar(8000) 
      declare @AndStr varchar(8000) 
      declare @Eq varchar(8000) 
      declare @IndId int
      declare @IndStatus int
      declare @CurrIndId smallint
      declare @CurrStatus int
      declare @UKey sysname 
      declare @Col varchar(128)
      declare @LastUsedCol varchar(128)
      declare @xType int
      declare @Len int
      declare @SelectStr varchar(8000) 
      declare @ExecSql nvarchar(1000) 
      declare @NotInDB1 bit 
      declare @NotInDB2 bit 
      declare @NotEq bit 
      declare @Numb int
      declare @Cnt1 int
      declare @Cnt2 int
      set @Numb = 0
      
      declare @StrInd int
      declare @i int
      declare @PrintStr varchar(8000)
      declare @ExecStr varchar(8000)
      declare TabCur cursor for 
      
      select d1o.name, d1u.name, d2u.name from '+@db1+'.dbo.sysobjects d1o, '+@db2+'.dbo.sysobjects d2o,
      '+@db1+'.dbo.sysusers d1u, '+@db2+'.dbo.sysusers d2u 
      where d1o.name = d2o.name and d1o.type = ''U'' and d2o.type = ''U''
      and d1o.uid = d1u.uid and d2o.uid = d2u.uid 
      and d1o.name not in (''dtproperties'') 
      and d1o.name in (select * from #TabToCheck)
      order by 1
      
      open TabCur 
      fetch next from TabCur into @Tab, @d1User, @d2User 
      while @@fetch_status = 0 
      begin 
      set @Numb = @Numb + 1
      print Char(13)+Char(10)+LTRIM(STR(@Numb))+''. TABLE: [''+@Tab+''] ''
      
      set @ExecSql = ''SELECT @Cnt = count(*) FROM '+@db1+'.[''+@d1User+''].[''+@Tab+'']''
      exec sp_executesql @ExecSql, N''@Cnt int output'', @Cnt = @Cnt1 output
      print CHAR(10)+STR(@Cnt1)+'' rows in '+@db1+'''
      set @ExecSql = ''SELECT @Cnt = count(*) FROM '+@db2+'.[''+@d2User+''].[''+@Tab+'']''
      exec sp_executesql @ExecSql, N''@Cnt int output'', @Cnt = @Cnt2 output
      print STR(@Cnt2)+'' rows in '+@db2+'''
      if @Cnt1 = 0 and @Cnt2 = 0
      begin
      exec ('' insert into #EmptyTables values(''''[''+@Tab+'']'''')'') 
      goto NextTab
      end
      set @KeyAndStr = '''' 
      set @KeyCommaStr = '''' 
      set @NotInDB1 = 0
      set @NotInDB2 = 0 
      set @NotEq = 0
      set @KeyAndStr = '''' 
      set @KeyCommaStr = '''' 
      truncate table #IndList1
      declare UKeys cursor fast_forward for 
      select i.indid, i.status, c.name, c.xType from '+@db1+'.dbo.sysobjects o, '+@db1+'.dbo.sysindexes i, '+@db1+'.dbo.sysindexkeys k, '+@db1+'.dbo.syscolumns c 
      where i.id = o.id and o.name = @Tab
      and (i.status & 2)<>0 
      and k.id = o.id and k.indid = i.indid 
      and c.id = o.id and c.colid = k.colid 
      order by i.indid, c.name
      open UKeys 
      fetch next from UKeys into @IndId, @IndStatus, @UKey, @xType
      set @CurrIndId = @IndId
      set @CurrStatus = @IndStatus
      while @@fetch_status = 0 
      begin 
      if @KeyAndStr <> ''''
      begin 
      set @KeyAndStr = @KeyAndStr + '' and '' + CHAR(10) 
      set @KeyCommaStr = @KeyCommaStr + '', '' 
      end 
      if @xType = 175 or @xType = 167 or @xType = 239 or @xType = 231 -- char, varchar, nchar, nvarchar
      begin
      set @KeyAndStr = @KeyAndStr + '' ISNULL(d1.[''+@UKey+''],''''!#null$'''')=ISNULL(d2.[''+@UKey+''],''''!#null$'''') ''
      end
      if @xType = 173 or @xType = 165 -- binary, varbinary
      begin
      set @KeyAndStr = @KeyAndStr +
      '' CASE WHEN d1.[''+@UKey+''] is null THEN 0x4D4FFB23A49411D5BDDB00A0C906B7B4 ELSE d1.[''+@UKey+''] END=''+
      ''CASE WHEN d2.[''+@UKey+''] is null THEN 0x4D4FFB23A49411D5BDDB00A0C906B7B4 ELSE d2.[''+@UKey+''] END ''
      end
      else if @xType = 56 or @xType = 127 or @xType = 60 or @xType = 122 -- int, 127 - bigint,60 - money, 122 - smallmoney
      begin
      set @KeyAndStr = @KeyAndStr + 
      '' CASE WHEN d1.[''+@UKey+''] is null THEN 971428763405345098745 ELSE d1.[''+@UKey+''] END=''+
      ''CASE WHEN d2.[''+@UKey+''] is null THEN 971428763405345098745 ELSE d2.[''+@UKey+''] END ''
      end
      else if @xType = 106 or @xType = 108 -- int, decimal, numeric
      begin
      set @KeyAndStr = @KeyAndStr + 
      '' CASE WHEN d1.[''+@UKey+''] is null THEN 71428763405345098745098.8723 ELSE d1.[''+@UKey+''] END=''+
      ''CASE WHEN d2.[''+@UKey+''] is null THEN 71428763405345098745098.8723 ELSE d2.[''+@UKey+''] END ''
      end
      else if @xType = 62 or @xType = 59 -- 62 - float, 59 - real
      begin 
      set @KeyAndStr = @KeyAndStr + 
      '' CASE WHEN d1.[''+@UKey+''] is null THEN 8764589764.22708E237 ELSE d1.[''+@UKey+''] END=''+
      ''CASE WHEN d2.[''+@UKey+''] is null THEN 8764589764.22708E237 ELSE d2.[''+@UKey+''] END ''
      end
      else if @xType = 52 or @xType = 48 or @xType = 104 -- smallint, tinyint, bit
      begin
      set @KeyAndStr = @KeyAndStr + '' CASE WHEN d1.[''+@UKey+''] is null THEN 99999 ELSE d1.[''+@UKey+''] END=''+
      ''CASE WHEN d2.[''+@UKey+''] is null THEN 99999 ELSE d2.[''+@UKey+''] END ''
      end
      else if @xType = 36 -- 36 - id 
      begin
      set @KeyAndStr = @KeyAndStr +
      '' CASE WHEN d1.[''+@UKey+''] is null''+
      '' THEN CONVERT(uniqueidentifier,''''1CD827A0-744A-4866-8401-B9902CF2D4FB'''')''+
      '' ELSE d1.[''+@UKey+''] END=''+
      ''CASE WHEN d2.[''+@UKey+''] is null''+
      '' THEN CONVERT(uniqueidentifier,''''1CD827A0-744A-4866-8401-B9902CF2D4FB'''')''+
      '' ELSE d2.[''+@UKey+''] END''
      end
      else if @xType = 61 or @xType = 58 -- datetime, smalldatetime
      begin
      set @KeyAndStr = @KeyAndStr +
      '' CASE WHEN d1.[''+@UKey+''] is null THEN ''''!#null$'''' ELSE CONVERT(varchar(40),d1.[''+@UKey+''],109) END=''+
      ''CASE WHEN d2.[''+@UKey+''] is null THEN ''''!#null$'''' ELSE CONVERT(varchar(40),d2.[''+@UKey+''],109) END ''
      end
      else if @xType = 189 -- timestamp (189) 
      begin
      set @KeyAndStr = @KeyAndStr + '' d1.[''+@UKey+'']=d2.[''+@UKey+''] ''
      end
      else if @xType = 98 -- SQL_variant
      begin
      set @KeyAndStr = @KeyAndStr + '' ISNULL(d1.[''+@UKey+''],''''!#null$'''')=ISNULL(d2.[''+@UKey+''],''''!#null$'''') ''
      end
      set @KeyCommaStr = @KeyCommaStr + '' d1.''+@UKey 
      fetch next from UKeys into @IndId, @IndStatus, @UKey, @xType
      if @IndId <> @CurrIndId
      begin
      insert into #IndList1 values (@CurrIndId, @CurrStatus, @KeyAndStr, @KeyCommaStr)
      set @CurrIndId = @IndId
      set @CurrStatus = @IndStatus
      set @KeyAndStr = ''''
      set @KeyCommaStr = '''' 
      end
      end 
      deallocate UKeys 
      insert into #IndList1 values (@CurrIndId, @CurrStatus, @KeyAndStr, @KeyCommaStr)'
      set @SqlStrGetListOfKeys2 = '
      set @KeyAndStr = '''' 
      set @KeyCommaStr = '''' 
      truncate table #IndList2
      declare UKeys cursor fast_forward for 
      select i.indid, i.status, c.name, c.xType from '+@db2+'.dbo.sysobjects o, '+@db2+'.dbo.sysindexes i, '+@db2+'.dbo.sysindexkeys k, '+@db2+'.dbo.syscolumns c 
      where i.id = o.id and o.name = @Tab
      and (i.status & 2)<>0 
      and k.id = o.id and k.indid = i.indid 
      and c.id = o.id and c.colid = k.colid 
      order by i.indid, c.name
      open UKeys 
      fetch next from UKeys into @IndId, @IndStatus, @UKey, @xType
      set @CurrIndId = @IndId
      set @CurrStatus = @IndStatus
      while @@fetch_status = 0 
      begin 
      if @KeyAndStr <> ''''
      begin 
      set @KeyAndStr = @KeyAndStr + '' and '' + CHAR(10) 
      set @KeyCommaStr = @KeyCommaStr + '', '' 
      end 
      if @xType = 175 or @xType = 167 or @xType = 239 or @xType = 231 -- char, varchar, nchar, nvarchar
      begin
      set @KeyAndStr = @KeyAndStr + '' ISNULL(d1.[''+@UKey+''],''''!#null$'''')=ISNULL(d2.[''+@UKey+''],''''!#null$'''') ''
      end
      if @xType = 173 or @xType = 165 -- binary, varbinary
      begin
      set @KeyAndStr = @KeyAndStr +
      '' CASE WHEN d1.[''+@UKey+''] is null THEN 0x4D4FFB23A49411D5BDDB00A0C906B7B4 ELSE d1.[''+@UKey+''] END=''+
      ''CASE WHEN d2.[''+@UKey+''] is null THEN 0x4D4FFB23A49411D5BDDB00A0C906B7B4 ELSE d2.[''+@UKey+''] END ''
      end
      else if @xType = 56 or @xType = 127 or @xType = 60 or @xType = 122 -- int, 127 - bigint,60 - money, 122 - smallmoney
      begin
      set @KeyAndStr = @KeyAndStr + 
      '' CASE WHEN d1.[''+@UKey+''] is null THEN 971428763405345098745 ELSE d1.[''+@UKey+''] END=''+
      ''CASE WHEN d2.[''+@UKey+''] is null THEN 971428763405345098745 ELSE d2.[''+@UKey+''] END ''
      end
      else if @xType = 106 or @xType = 108 -- int, decimal, numeric
      begin
      set @KeyAndStr = @KeyAndStr + 
      '' CASE WHEN d1.[''+@UKey+''] is null THEN 71428763405345098745098.8723 ELSE d1.[''+@UKey+''] END=''+
      ''CASE WHEN d2.[''+@UKey+''] is null THEN 71428763405345098745098.8723 ELSE d2.[''+@UKey+''] END ''
      end
      else if @xType = 62 or @xType = 59 -- 62 - float, 59 - real
      begin 
      set @KeyAndStr = @KeyAndStr + 
      '' CASE WHEN d1.[''+@UKey+''] is null THEN 8764589764.22708E237 ELSE d1.[''+@UKey+''] END=''+
      ''CASE WHEN d2.[''+@UKey+''] is null THEN 8764589764.22708E237 ELSE d2.[''+@UKey+''] END ''
      end
      else if @xType = 52 or @xType = 48 or @xType = 104 -- smallint, tinyint, bit
      begin
      set @KeyAndStr = @KeyAndStr + '' CASE WHEN d1.[''+@UKey+''] is null THEN 99999 ELSE d1.[''+@UKey+''] END=''+
      ''CASE WHEN d2.[''+@UKey+''] is null THEN 99999 ELSE d2.[''+@UKey+''] END ''
      end
      else if @xType = 36 -- 36 - id 
      begin
      set @KeyAndStr = @KeyAndStr +
      '' CASE WHEN d1.[''+@UKey+''] is null''+
      '' THEN CONVERT(uniqueidentifier,''''1CD827A0-744A-4866-8401-B9902CF2D4FB'''')''+
      '' ELSE d1.[''+@UKey+''] END=''+
      ''CASE WHEN d2.[''+@UKey+''] is null''+
      '' THEN CONVERT(uniqueidentifier,''''1CD827A0-744A-4866-8401-B9902CF2D4FB'''')''+
      '' ELSE d2.[''+@UKey+''] END''
      end
      else if @xType = 61 or @xType = 58 -- datetime, smalldatetime
      begin
      set @KeyAndStr = @KeyAndStr +
      '' CASE WHEN d1.[''+@UKey+''] is null THEN ''''!#null$'''' ELSE CONVERT(varchar(40),d1.[''+@UKey+''],109) END=''+
      ''CASE WHEN d2.[''+@UKey+''] is null THEN ''''!#null$'''' ELSE CONVERT(varchar(40),d2.[''+@UKey+''],109) END ''
      end
      else if @xType = 189 -- timestamp (189) 
      begin
      set @KeyAndStr = @KeyAndStr + '' d1.[''+@UKey+'']=d2.[''+@UKey+''] ''
      end
      else if @xType = 98 -- SQL_variant
      begin
      set @KeyAndStr = @KeyAndStr + '' ISNULL(d1.[''+@UKey+''],''''!#null$'''')=ISNULL(d2.[''+@UKey+''],''''!#null$'''') ''
      end
      set @KeyCommaStr = @KeyCommaStr + '' d1.''+@UKey 
      fetch next from UKeys into @IndId, @IndStatus, @UKey, @xType
      if @IndId <> @CurrIndId
      begin
      insert into #IndList2 values (@CurrIndId, @CurrStatus, @KeyAndStr, @KeyCommaStr)
      set @CurrIndId = @IndId
      set @CurrStatus = @IndStatus
      set @KeyAndStr = ''''
      set @KeyCommaStr = '''' 
      end
      end 
      deallocate UKeys 
      insert into #IndList2 values (@CurrIndId, @CurrStatus, @KeyAndStr, @KeyCommaStr)
      set @KeyCommaStr = null
      
      select @KeyCommaStr=i1.KeyCommaStr from #IndList1 i1
      join #IndList2 i2 on i1.KeyCommaStr = i2.KeyCommaStr
      where (i1.IndStatus & 2048)<> 0 and (i2.IndStatus & 2048)<>0
      
      if @KeyCommaStr is null 
      set @KeyCommaStr = (select top 1 i1.KeyCommaStr from #IndList1 i1
      join #IndList2 i2 on i1.KeyCommaStr = i2.KeyCommaStr)
      set @KeyAndStr = (select TOP 1 KeyAndStr from #IndList1 where KeyCommaStr = @KeyCommaStr)
      if @KeyCommaStr is null
      set @KeyCommaStr = ''''
      if @KeyAndStr is null
      set @KeyAndStr = '''''
      set @SqlStrGetListOfColumns = '
      set @AndStr = ''''
      set @StrInd = 1
      declare Cols cursor local fast_forward for 
      select c.name, c.xtype, c.length from '+@db1+'.dbo.sysobjects o, '+@db1+'.dbo.syscolumns c
      where o.id = c.id and o.name = @Tab 
      and CHARINDEX(c.name, @KeyCommaStr) = 0
      open Cols 
      fetch next from Cols into @Col, @xType, @len
      while @@fetch_status = 0 
      begin 
      if @xType = 175 or @xType = 167 or @xType = 239 or @xType = 231 -- char, varchar, nchar, nvarchar
      begin
      set @Eq = ''ISNULL(d1.[''+@Col+''],''''!#null$'''')=ISNULL(d2.[''+@Col+''],''''!#null$'''') ''
      end
      if @xType = 173 or @xType = 165 -- binary, varbinary
      begin
      set @Eq = ''CASE WHEN d1.[''+@Col+''] is null THEN 0x4D4FFB23A49411D5BDDB00A0C906B7B4 ELSE d1.[''+@Col+''] END=''+
      ''CASE WHEN d2.[''+@Col+''] is null THEN 0x4D4FFB23A49411D5BDDB00A0C906B7B4 ELSE d2.[''+@Col+''] END ''
      end
      else if @xType = 56 or @xType = 127 or @xType = 60 or @xType = 122 -- int, 127 - bigint,60 - money, 122 - smallmoney
      begin
      set @Eq = ''CASE WHEN d1.[''+@Col+''] is null THEN 971428763405345098745 ELSE d1.[''+@Col+''] END=''+
      ''CASE WHEN d2.[''+@Col+''] is null THEN 971428763405345098745 ELSE d2.[''+@Col+''] END ''
      end
      else if @xType = 106 or @xType = 108 -- int, decimal, numeric
      begin
      set @Eq = ''CASE WHEN d1.[''+@Col+''] is null THEN 71428763405345098745098.8723 ELSE d1.[''+@Col+''] END=''+
      ''CASE WHEN d2.[''+@Col+''] is null THEN 71428763405345098745098.8723 ELSE d2.[''+@Col+''] END ''
      end
      else if @xType = 62 or @xType = 59 -- 62 - float, 59 - real
      begin 
      set @Eq = ''CASE WHEN d1.[''+@Col+'']
      

      【讨论】:

        【解决方案3】:

        首先我建议你编写你想要的整个数据库。将此脚本用作定义数据库体系结构的单个位置。它的直接目的是在两台服务器上创建相同的数据库,从长远来看,您可以维护该脚本以反映结构。之后,只需创建新数据库并将旧数据库中的数据复制到新数据库即可。

        【讨论】:

        • 我认为这不会很好。因为我在两个数据库中都有不同的变化。我不确定我是否认识所有这些。我不能写一个实际扫描两台服务器的存储过程,如果 key = match 然后选择 insert else create new(这些行上的东西)
        • 不,我只是建议您将包含合并结果的数据库定义为脚本并维护它。它比 SQL Server 自动生成的脚本更有帮助。在您定义了您希望数据的样子之后,尽管在某些地方并不简单,但是将数据从现有数据库中提取到这个新数据库的任务很简单。是否要编写此过程的脚本取决于个人喜好。
        【解决方案4】:

        首先,不要再在两者之间做任何区别了!

        接下来,整理表格不兼容的地方。编写每个数据库的所有表、约束和视图的脚本,并执行DIFF 以查看组合数据时会遇到什么结构性问题。如果您使用identities,您将需要解决如何混合数据。是否存在名称相同但结果不同的视图?你需要决定如何处理这些。您可以对其中一个数据库进行增量更改,使其与另一个数据库更加兼容,和/或您可以计划一个大规模的转换脚本。

        当您掌握了这一点时,构建一个可以包含两个数据库的新模式。从那里开始担心存储过程和业务逻辑,使用相同的DIFF 方法。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-09-30
          相关资源
          最近更新 更多