Реализовать симметричную разницу в SQL Server?

Вот проблема, которую я пытался решить на работе. Я не эксперт по базам данных, так что, возможно, это немного второкурсник. Все извинения.

У меня есть заданная база данных D, которая была продублирована на другом компьютере (возможно, сомнительным образом), в результате чего возникла база данных D'. Моя задача проверить, что базы данных D и D 'фактически идентичны.

Проблема, конечно, в том, что на самом деле делать, если это не так. Для этой цели я думал запустить симметричную разность для каждой соответствующей таблицы и увидеть различия.

Существует "большое" количество таблиц, поэтому я не хочу запускать каждое симметричное различие вручную. Как мне тогда реализовать симметричную разностную "функцию" (или хранимую процедуру, или что угодно), которая может выполняться на произвольных таблицах без явного перечисления столбцов?

Это работает на Windows, и ваш хедж-фонд взорвется, если вы не выполните его. Удачи.

5 ответов

Решение

Моя первая реакция состоит в том, чтобы предложить дублирование на другую машину снова без сомнений.

Если это не вариант, возможно, некоторые инструменты, доступные в Red Gate, могут сделать то, что вам нужно.

(Я никоим образом не связан с Red Gate, просто помню, как Джоэл упоминал, насколько хороши их инструменты на подкасте.)

Вот решение. Данные примера взяты из базы данных ReportServer, поставляемой с SSRS 2008 R2, но вы можете использовать ее в любом наборе данных:

SELECT s.name, s.type 
FROM 
(
    SELECT s1.name, s1.type
    FROM syscolumns s1
    WHERE object_name(s1.id) = 'executionlog2'
    UNION ALL 
    SELECT s2.name, s2.type
    FROM syscolumns s2 
    WHERE object_name(s2.id) = 'executionlog3'
) AS s 
GROUP BY s.name, s.type   
HAVING COUNT(s.name) = 1

Вы можете достичь этого, делая что-то вроде этого.

Я использовал функцию для разделения значения через запятую в таблицу для демонстрации.

CREATE FUNCTION [dbo].[Split]
(
    @RowData nvarchar(2000),
    @SplitOn nvarchar(5)
)  
RETURNS @RtnValue table 
(
    Id int identity(1,1),
    Data nvarchar(100)
) 
AS  
BEGIN 
    Declare @Cnt int
    Set @Cnt = 1

    While (Charindex(@SplitOn,@RowData)>0)
    Begin
        Insert Into @RtnValue (data)
        Select 
            Data = ltrim(rtrim(Substring(@RowData,1,Charindex(@SplitOn,@RowData)-1)))

        Set @RowData = Substring(@RowData,Charindex(@SplitOn,@RowData)+1,len(@RowData))
        Set @Cnt = @Cnt + 1
    End

    Insert Into @RtnValue (data)
    Select Data = ltrim(rtrim(@RowData))

    Return
END
GO


DECLARE @WB_LIST varchar(1024) = '123,125,764,256,157';
DECLARE @WB_LIST_IN_DB varchar(1024) = '123,125,795,256,157,789';

DECLARE @TABLE_UPDATE_LIST_IN_DB TABLE ( id varchar(20));
DECLARE @TABLE_UPDATE_LIST TABLE ( id varchar(20));

INSERT INTO @TABLE_UPDATE_LIST
SELECT data FROM dbo.Split(@WB_LIST,',');

INSERT INTO @TABLE_UPDATE_LIST_IN_DB
SELECT data FROM dbo.Split(@LIST_IN_DB,',');


SELECT * FROM @TABLE_UPDATE_LIST
EXCEPT
SELECT * FROM @TABLE_UPDATE_LIST_IN_DB
UNION
SELECT * FROM @TABLE_UPDATE_LIST_IN_DB
EXCEPT
SELECT * FROM @TABLE_UPDATE_LIST;

SQL Server 2000 добавлено ключевое слово "EXCEPT", которое практически совпадает с "минусом" Oracle

SELECT * FROM TBL_A WHERE ...
EXCEPT
SELECT * FROM TBL_B WHERE ...

Используйте инструменты SQL Compare от Red Gate. Он сравнивает схемы, а инструмент сравнения данных SQL сравнивает данные. Я думаю, что вы можете получить бесплатную пробную версию для них, но вы могли бы также купить их, если это повторяющаяся проблема. Там могут быть с открытым исходным кодом или бесплатные инструменты, как это, но вы могли бы просто получить это.

Другие вопросы по тегам