2010-01-25 2 views
19

В принципе, у нас есть одна таблица (original table) и она подставлена ​​в другой стол (backup table); таким образом, обе таблицы имеют точно такую ​​же схему.Как проверить, имеют ли две таблицы одинаковые данные?

В начале обе таблицы (original table и backup table) содержат точно такой же набор данных. После некоторого времени по какой-то причине мне нужно проверить, изменился ли набор данных в original table или нет.

Для этого мне нужно сравнить набор данных в original table с backup table.

Скажем original table имеет следующую схему:

create table LemmasMapping (
    lemma1 int, 
    lemma2 int, 
    index ix_lemma1 using btree (lemma1), 
    index ix_lemma2 using btree (lemma2) 
) 

Как я мог достичь сравнения набора данных?

Обновление: таблица не имеет первичного ключа. Он просто хранит сопоставления между двумя идентификаторами.

ответ

13

Я хотел бы написать три запроса.

  1. Внутреннее соединение подобрать строки, где первичный ключ существует в обеих таблицах, но есть разница в стоимости одного или нескольких других столбцов. Это приведет к замене строк в оригинале.

  2. Левое внешнее соединение, чтобы забрать строки, которые находятся в исходных таблицах, но не в таблице резервного копирования (то есть в строке в оригинале есть первичный ключ, который не существует в резервной копии). Это вернет строки, вставленные в оригинал.

  3. Правое внешнее соединение, чтобы забрать строки в резервной копии, которые больше не существуют в оригинале. Это приведет к возврату строк, которые были удалены из оригинала.

Вы можете объединить три запроса вместе, чтобы вернуть единый результирующий набор. Если вы это сделали, вам нужно будет добавить столбец, чтобы указать, какой тип строки (обновленный, вставленный или удаленный).

С небольшим усилием вы могли бы сделать это в одном запросе, используя полное внешнее соединение. Будьте осторожны с внешними соединениями, поскольку они ведут себя по-разному в разных SQL-машинах. Предикаты, помещенные в предложение where, вместо предложения join иногда могут превратить ваше внешнее соединение во внутреннее соединение.

+0

Это работает. Благодаря! –

+2

«Будьте осторожны с внешними соединениями, так как они ведут себя по-разному в разных SQL-машинах *» - подумайте об этом? Я не видел ни одной СУБД, которая делает вещи по-разному, когда используется внешнее соединение. "* Предикаты, помещенные в предложение where, вместо предложения join иногда могут превратить ваше внешнее соединение во внутреннее соединение *" - да, конечно, они будут, если эти предикаты используют столбцы из «внешней таблицы». При сравнении нулевого значения с постоянным значением строки с нулями будут отброшены. –

+0

Майк, не могли бы вы предоставить запрос. thanks ^^ – stacheldraht27

1
select count(*) 
from lemmas as original_table 
     full join backup_table using (lemma_id) 
where backup_table.lemma_id is null 
     or original_table.lemma_id is null 
     or original_table.lemma != backup_table.lemma 

Полное соединение/проверка на нуль должно охватывать дополнения или удаления, а также изменения.

  • backup.id является Null = дополнение
  • original.id равно нулю = удаление
  • не пустое = изменение
+0

Хорошая идея, за исключением того факта, что MySQL не поддерживает полное внешнее объединение. –

28

Вы можете использовать CHECKSUM TABLE и сравнивать результаты поиска. Вы можете даже alter the table включить живые контрольные суммы, чтобы они были постоянно доступны.

CHECKSUM TABLE original_table, backup_table; 

Это не требует, чтобы в таблицах был первичный ключ.

+1

+1 для контрольной суммы –

+3

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

+0

По-видимому, функция отсутствует в PostgreSQL. –

0

Для более ленивого или более SQL-разработчика, работающего с MS SQL Server, я бы рекомендовал SQL Delta (www.sqldelta.com) для этого и любого другого типа работы с базой данных. Он имеет большой графический интерфейс, быстрый и точный и может различать все объекты базы данных, создавать и запускать необходимые сценарии изменений, синхронизировать целые базы данных. Его следующая лучшая вещь для DBA ;-)

Я думаю, что есть аналогичный инструмент, доступный от RedGate под названием SQL Compare. Я считаю, некоторые выпуски последней версии Visual Studio (2010) также включают очень похожий инструмент.

+0

UPDATE. Я использовал инструменты сравнения данных в VS2010 и имхо, они не подходят, как ботинки любого из продуктов выше ... – 5arx

15
SELECT * FROM Table1 
UNION 
SELECT * FROM Table2 

Если вы получаете записи больше, чем любая из двух таблиц, у них нет одинаковых данных.

+0

Невозможно ли «выбрать счетчик (*) из T1 union select count (*) из T2'? – nvlass

+0

К сожалению, нет. Это будет только объединение объединений, поэтому, если у них будет одинаковое количество, это будет иметь только одну строку. – crunkchitis

+0

Когда вы говорите * записи больше, чем любая из двух таблиц, у них нет одинаковых данных * вы имеете в виду, если таблица a имеет 20 строк, а таблица b имеет 20 строк, если они объединяют более 20 строк, тогда таблица a и таблица b не идентичны? – gh0st

1

Попробуйте следующие сравнить две таблицы:

SELECT 'different' FROM DUAL WHERE EXISTS(
    SELECT * FROM (
     SELECT /*DISTINCT*/ +1 AS chk,a.c1,a.c2,a.c3 FROM a 
     UNION ALL 
     SELECT /*DISTINCT*/ +1 AS chk,b.c1,b.c2,b.c3 FROM b 
    ) c 
    GROUP BY c1,c2,c3 
    HAVING SUM(chk)<>2 
) 
UNION SELECT 'equal' FROM DUAL 
LIMIT 1; 
0

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

Шаг 1 - Тест для повторяющихся строк на TABLEA

Если SELECT DISTINCT * FROM TABLEA

имеет подсчитывать ту же строку,

SELECT * FROM TABLEA

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

Шаг 2 - Тест на дубликате строки на TableB

Если SELECT DISTINCT * FROM TableB

имеет кол ту же строку,

SELECT * FROM TableB

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

Шаг 3 - INNER JOIN TABLEA в TableB на каждой колонке

Если количество строк в поле ниже запроса имеет то же количество строк, что и число строк из шаги 1 и 2, а затем таблицы одинаковы:

SELECT 
* 

FROM 
TABLEA 

INNER JOIN TABLEA ON 
TABLEA.column1 = TABLEB.column1 
AND TABLEA.column2 = TABLEB.column2 
AND TABLEA.column3 = TABLEB.column3 
--etc...for every column 

Следует отметить, что этот метод д не обязательно тестировать разные типы данных и, вероятно, не будет работать на несовместимых типах данных (например, VARBINARY)

Отзыв добро пожаловать!