Muitos colegas já tiveram a necessidade de comparar duas bases de dados no SQL Server para analisar rapidamente a diferença entre elas.
Como é algo recorrente, estou publicando aqui uma consulta (query) que compara a estrutura de duas bases e destaca tabelas e campos que existem em uma e não na outra, bidirecionalmente.
Bases de exemplo
Imagine que você tem um BANCO_A
:
use BANCO_A;
go
create table Person (
id int primary key identity,
name varchar(100),
height numeric(4,1)
);
create table Car (
id int primary key identity,
brand varchar(100),
model varchar(100),
year int
);
create table Animal (
id int primary key identity,
name varchar(100),
kind varchar(100)
);
E também um BANCO_B
:
use BANCO_B;
go
create table Person (
id int primary key identity,
name varchar(100)
);
create table Car (
id int primary key identity,
brand varchar(100),
model varchar(100),
year float,
kilometers int
);
create table Pet (
id int primary key identity,
name varchar(100)
);
Verificando tabelas adicionadas e excluídas
Para identificar somente as tabelas que foram adicionadas ou excluídas de uma base para outra, use a seguinte consulta:
SELECT T1.TABLE_NAME 'DB1 TABLE', T2.TABLE_NAME 'DB2 TABLE'
FROM BANCO_A.INFORMATION_SCHEMA.TABLES T1
FULL JOIN BANCO_B.INFORMATION_SCHEMA.TABLES T2
ON T1.TABLE_NAME = T2.TABLE_NAME
ORDER BY ISNULL(T1.TABLE_NAME, T2.TABLE_NAME)
Verificando colunas adicionadas e excluídas
Para verificar as diferenças tanto das tabelas como das colunas que elas contém, use a seguinte consulta:
SELECT DB1.TABLE_NAME 'DB1 TABLE', DB1.COLUMN_NAME 'DB1 COLUMN', DB1.DATA_TYPE 'DB1 TYPE',
DB2.TABLE_NAME 'DB2 TABLE', DB2.COLUMN_NAME 'DB1 COLUMN', DB2.DATA_TYPE 'DB2 TYPE'
FROM (
SELECT T1.TABLE_NAME, C1.COLUMN_NAME, C1.DATA_TYPE
FROM BANCO_A.INFORMATION_SCHEMA.TABLES T1
JOIN BANCO_A.INFORMATION_SCHEMA.COLUMNS C1
ON C1.TABLE_NAME = T1.TABLE_NAME
) DB1
FULL JOIN (
SELECT T2.TABLE_NAME, C2.COLUMN_NAME, C2.DATA_TYPE
FROM BANCO_B.INFORMATION_SCHEMA.TABLES T2
JOIN BANCO_B.INFORMATION_SCHEMA.COLUMNS C2
ON C2.TABLE_NAME = T2.TABLE_NAME
) DB2
ON DB1.TABLE_NAME = DB2.TABLE_NAME
AND DB1.COLUMN_NAME = DB2.COLUMN_NAME
ORDER BY ISNULL(DB1.TABLE_NAME, DB2.TABLE_NAME), ISNULL(DB1.COLUMN_NAME, DB2.COLUMN_NAME)
Executando a consulta dinamicamente
Nos dois exemplos acima, basta trocar BANCO_A
e BANCO_B
por duas bases que você precisa comparar.
Entretanto, pode ser que você queira criar uma procedure ou rotina que compare duas bases quaisquer.
Para isso você pode executar uma consulta dinâmica usando o comando SP_SQLEXEC
. Veja o seguinte exemplo:
DECLARE
@BANCO1 NVARCHAR(100) = 'BANCO_A',
@BANCO2 NVARCHAR(100) = 'BANCO_B',
@SQL NVARCHAR(2000)
SET @SQL = N'SELECT T1.TABLE_NAME ''DB1 TABLE'', T2.TABLE_NAME ''DB2 TABLE''
FROM ' + @BANCO1 + '.INFORMATION_SCHEMA.TABLES T1
FULL JOIN ' + @BANCO2 + '.INFORMATION_SCHEMA.TABLES T2
ON T1.TABLE_NAME = T2.TABLE_NAME
ORDER BY ISNULL(T1.TABLE_NAME, T2.TABLE_NAME)';
EXEC sp_sqlexec @SQL
Agora basta alterar o valor das variáveis ou receber os nomes das duas bases através de parâmetros.
Duas observações importantes:
- O parâmetro da rotina
SP_SQLEXEC
deve ser do tipoNVARCHAR
. - Não tente fazer a concatenação de variáveis e literais diretamente no argumento dessa rotina. Faça isso sempre antes e então passe uma variável como argumento. Não fiz o teste em todas as versões do SQL Server, mas nas que usei deve ser desta forma.