web-dev-qa-db-fra.com

Comment comparer des données entre deux tables de bases de données différentes avec Sql Server 2008?

J'ai deux bases de données, nommées DB1 et DB2 dans Sql Server 2008. Ces deux bases de données ont les mêmes tables et les mêmes données de table. Cependant, je veux vérifier s’il existe des différences entre les données de ces tableaux. 

Quelqu'un pourrait-il m'aider avec un script pour cela? 

38
Jagadis Sahu
select * 
from (
      select *
      from DB1.dbo.Table
      except
      select *
      from DB2.dbo.Table
     ) as T
union all
select * 
from (
      select *
      from DB2.dbo.Table
      except
      select *
      from DB1.dbo.Table
     ) as T

Code de test:

declare @T1 table (ID int)
declare @T2 table (ID int)

insert into @T1 values(1),(2)
insert into @T2 values(2),(3)

select * 
from (
      select *
      from @T1
      except
      select *
      from @T2
     ) as T
union all
select * 
from (
      select *
      from @T2
      except
      select *
      from @T1
     ) as T

Résultat:

ID
-----------
1
3
25
Mikael Eriksson

Je suggérerais vraiment que les personnes rencontrant ce problème aillent chercher un outil de comparaison de base de données tiers. 

Raison - ces outils permettent de gagner beaucoup de temps et rendent le processus moins sujet aux erreurs. 

J’ai utilisé des outils de comparaison d’ApexSQL (Diff et Data Diff), mais vous ne pouvez pas vous tromper avec d’autres outils déjà mentionnés par marc_s et Marina Nastenko.

Si vous êtes absolument certain de ne comparer que les tables une seule fois, le langage SQL convient, mais si vous en avez besoin de temps en temps, vous aurez intérêt à utiliser un outil tiers.

_ {Si vous n'avez pas de budget pour l'acheter, utilisez-le simplement en mode d'évaluation pour faire le travail.} _

J'espère que les nouveaux lecteurs trouveront cela utile même s’il s’agit d’une réponse tardive…

24
JdMR

J'ai fait des choses comme ça en utilisant la fonction Checksum (*)

En principe, il crée une somme de contrôle au niveau de la ligne pour toutes les données de colonnes. Vous pouvez ensuite comparer la somme de contrôle de chaque ligne de chaque table. Utilisez une jointure à gauche pour rechercher des lignes différentes.

J'espère que ça a du sens ...

Mieux avec un exemple ....

select *
from 
( select checksum(*) as chk, userid as k from UserAccounts) as t1
left join 
( select checksum(*) as chk, userid as k from UserAccounts) as t2 on t1.k = t2.k
where t1.chk <> t2.chk 
7
Matt

Comparaison des deux bases de données dans la base de données SQL. Essayez cette requête, cela peut aider.

SELECT T.[name] AS [table_name], AC.[name] AS [column_name],  TY.[name] AS 
   system_data_type FROM    [***Database Name 1***].sys.[tables] AS T  
   INNER JOIN [***Database Name 1***].sys.[all_columns] AC ON T.[object_id] = AC.[object_id]      
   INNER JOIN [***Database Name 1***].sys.[types] TY ON AC.[system_type_id] = TY.[system_type_id] 
   EXCEPT SELECT T.[name] AS [table_name], AC.[name] AS [column_name], TY.[name] AS system_data_type FROM    ***Database Name 2***.sys.[tables] AS T  
   INNER JOIN ***Database Name 2***.sys.[all_columns] AC ON T.[object_id] = AC.[object_id]  
   INNER JOIN ***Database Name 2***.sys.[types] TY ON AC.[system_type_id] = TY.[system_type_id]
4
edward
select * from DB1.dbo.Table a inner join DB2.dbo.Table b on b.PrimKey = a.PrimKey 
where a.FirstColumn <> b.FirstColumn ...

La somme de contrôle recommandée par Matt est probablement une meilleure approche pour comparer des colonnes plutôt que de comparer chaque colonne.

3
evpo

Si la base de données se trouve sur le même serveur, utilisez le format [DatabaseName].[Owner].[TableName] lorsque vous accédez à une table qui réside dans une base de données différente.

Exemple: [DB1].[dbo].[TableName]

Si les bases de données de différents serveurs examinent/ Création de serveurs liés (moteur de base de données SQL Server)

2
CharithJ

Une autre solution (non T-SQL): vous pouvez utiliser tablediff utility. Par exemple, si vous souhaitez comparer deux tables (Localitate) de deux serveurs différents (ROBUH01 et ROBUH02), vous pouvez utiliser cette commande Shell:

C:\Program Files\Microsoft SQL Server\100\COM>tablediff -sourceserver ROBUH01 -s
ourcedatabase SIM01 -sourceschema dbo -sourcetable Localitate -destinationserver
 ROBUH02 -destinationschema dbo -destinationdatabase SIM02 -destinationtable Lo
calitate

Résultats:

Microsoft (R) SQL Server Replication Diff Tool Copyright (c) 2008 Microsoft Corporation User-specified agent parameter values: 
-sourceserver ROBUH01 
-sourcedatabase SIM01 
-sourceschema dbo 
-sourcetable Localitate 
-destinationserver ROBUH02 
-destinationschema dbo 
-destinationdatabase SIM02 
-destinationtable Localitate 

Table [SIM01].[dbo].[Localitate] on ROBUH01 and Table [SIM02].[dbo].[Localitate ] on ROBUH02 have 10 differences. 

Err Id Dest. 
Only 21433 Dest. 
Only 21434 Dest. 
Only 21435 Dest. 
Only 21436 Dest. 
Only 21437 Dest. 
Only 21438 Dest. 
Only 21439 Dest. 
Only 21441 Dest. 
Only 21442 Dest. 
Only 21443 
The requested operation took 9,9472657 seconds.
------------------------------------------------------------------------
1
Bogdan Sahlean

Afin de comparer deux bases de données, j'ai écrit les procédures ci-dessous . Si vous souhaitez comparer deux tables, vous pouvez utiliser la procédure 'CompareTables'. Exemple :

EXEC master.dbo.CompareTables 'DB1', 'dbo', 'table1', 'DB2', 'dbo', 'table2'

Si vous souhaitez comparer deux bases de données, utilisez la procédure 'CompareDatabases'. Exemple :

EXEC master.dbo.CompareDatabases 'DB1', 'DB2'

Remarque: - J'ai essayé de sécuriser les procédures, mais elles ne concernent que les tests et le débogage. Si vous souhaitez une solution complète à des fins de comparaison, utilisez une tierce partie comme (Visual Studio, ...)

USE [master]
GO

create proc [dbo].[CompareDatabases]
    @FirstDatabaseName nvarchar(50),
    @SecondDatabaseName nvarchar(50)
    as
begin
    -- Check that databases exist
    if not exists(SELECT name FROM sys.databases WHERE name=@FirstDatabaseName)
        return 0
    if not exists(SELECT name FROM sys.databases WHERE name=@SecondDatabaseName)
        return 0

    declare @result table (TABLE_NAME nvarchar(256))
    SET NOCOUNT ON
    insert into @result EXEC('(Select distinct TABLE_NAME from ' + @FirstDatabaseName  + '.INFORMATION_SCHEMA.COLUMNS '
                                    +'Where TABLE_SCHEMA=''dbo'')'
                            + 'intersect'
                            + '(Select distinct TABLE_NAME from ' + @SecondDatabaseName  + '.INFORMATION_SCHEMA.COLUMNS '
                                    +'Where TABLE_SCHEMA=''dbo'')')

    DECLARE @TABLE_NAME nvarchar(256)
    DECLARE curseur CURSOR FOR
        SELECT TABLE_NAME FROM @result
    OPEN curseur
    FETCH curseur INTO @TABLE_NAME
        WHILE @@FETCH_STATUS = 0
            BEGIN
                print 'TABLE : ' + @TABLE_NAME
                EXEC master.dbo.CompareTables @FirstDatabaseName, 'dbo', @TABLE_NAME, @SecondDatabaseName, 'dbo', @TABLE_NAME
                FETCH curseur INTO @TABLE_NAME
            END
        CLOSE curseur
    DEALLOCATE curseur
    SET NOCOUNT OFF
end
GO

.

USE [master]
GO

CREATE PROC [dbo].[CompareTables]
    @FirstTABLE_CATALOG nvarchar(256),
    @FirstTABLE_SCHEMA nvarchar(256),
    @FirstTABLE_NAME nvarchar(256),
    @SecondTABLE_CATALOG nvarchar(256),
    @SecondTABLE_SCHEMA nvarchar(256),
    @SecondTABLE_NAME nvarchar(256)
    AS
BEGIN
    -- Verify if first table exist
    DECLARE @table1 nvarchar(256) = @FirstTABLE_CATALOG + '.' + @FirstTABLE_SCHEMA + '.' + @FirstTABLE_NAME
    DECLARE @return_status int
    EXEC @return_status = master.dbo.TableExist @FirstTABLE_CATALOG, @FirstTABLE_SCHEMA, @FirstTABLE_NAME
    IF @return_status = 0
        BEGIN
            PRINT @table1 + ' : Table Not FOUND'
            RETURN 0
        END



    -- Verify if second table exist
    DECLARE @table2 nvarchar(256) = @SecondTABLE_CATALOG + '.' + @SecondTABLE_SCHEMA + '.' + @SecondTABLE_NAME
    EXEC @return_status = master.dbo.TableExist @SecondTABLE_CATALOG, @SecondTABLE_SCHEMA, @SecondTABLE_NAME
    IF @return_status = 0
        BEGIN
            PRINT @table2 + ' : Table Not FOUND'
            RETURN 0
        END

    -- Compare the two tables
    DECLARE @sql AS NVARCHAR(MAX)
    SELECT @sql = '('
                + '(SELECT ''' + @table1 + ''' as _Table, * FROM ' + @FirstTABLE_CATALOG + '.' + @FirstTABLE_SCHEMA + '.' + @FirstTABLE_NAME + ')'
                + 'EXCEPT'
                + '(SELECT ''' + @table1 + ''' as _Table, * FROM ' + @SecondTABLE_CATALOG + '.' + @SecondTABLE_SCHEMA + '.' + @SecondTABLE_NAME + ')'
                + ')'
                + 'UNION'
                + '('
                + '(SELECT ''' + @table2 + ''' as _Table, * FROM ' + @SecondTABLE_CATALOG + '.' + @SecondTABLE_SCHEMA + '.' + @SecondTABLE_NAME + ')'
                + 'EXCEPT'
                + '(SELECT ''' + @table2 + ''' as _Table, * FROM ' + @FirstTABLE_CATALOG + '.' + @FirstTABLE_SCHEMA + '.' + @FirstTABLE_NAME + ')'
                + ')'
    DECLARE @wrapper AS NVARCHAR(MAX) = 'if exists (' + @sql + ')' + char(10) + '    (' + @sql + ')ORDER BY 2'
    Exec(@wrapper)
END
GO

.

USE [master]
GO

CREATE PROC [dbo].[TableExist]
    @TABLE_CATALOG nvarchar(256),
    @TABLE_SCHEMA nvarchar(256),
    @TABLE_NAME nvarchar(256)
    AS
BEGIN
    IF NOT EXISTS(SELECT name FROM sys.databases WHERE name=@TABLE_CATALOG)
        RETURN 0

    declare @result table (TABLE_SCHEMA nvarchar(256), TABLE_NAME nvarchar(256))
    SET NOCOUNT ON
    insert into @result EXEC('Select TABLE_SCHEMA, TABLE_NAME from ' + @TABLE_CATALOG  + '.INFORMATION_SCHEMA.COLUMNS')
    SET NOCOUNT OFF

    IF EXISTS(SELECT TABLE_SCHEMA, TABLE_NAME FROM @result
                WHERE TABLE_SCHEMA=@TABLE_SCHEMA AND TABLE_NAME=@TABLE_NAME)
        RETURN 1

    RETURN 0
END

GO
0
MOULOU

Si les deux bases de données sur le même serveur. Vous pouvez vérifier des tables similaires en utilisant la requête suivante:

select 
      fdb.name, sdb.name 
from 
      FIRSTDBNAME.sys.tables fdb 
      join SECONDDBNAME.sys.tables sdb
      on fdb.name = sdb.name -- compare same name tables
order by 
      1     

En listant un tableau similaire, vous pouvez comparer le schéma des colonnes en utilisant la vue sys.columns.

J'espère que cela vous aide.

0
user3209145