SQL - Проверить таблицу на наличие новых строк? - PullRequest
4 голосов
/ 24 июня 2009

У меня есть две таблицы, например:

Table A                                  Table B
=======                                  =======

Name         | Color                     Name         | Color
----------------------                   ----------------------
Mickey Mouse | red                       Mickey Mouse | red
Donald Duck  | green                     Donald Duck  | blue
Donald Duck  | blue                      Minnie       | red
Goofy        | black
Minnie       | red

Таблица A - это моя исходная таблица, а B - таблица назначения. Теперь мне нужен запрос, который находит все различные (дополнительные) строки в таблице A, поэтому таблица B может быть обновлена ​​этими строками. Поэтому мне нужен запрос, который находит мне следующие строки из таблицы A:

Name         | Color  
----------------------
Donald Duck  | green  
Goofy        | black

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

Ответы [ 11 ]

9 голосов
/ 24 июня 2009

Я бы использовал структуру NOT EXISTS.

SELECT Name, Color
FROM TableA
WHERE NOT EXISTS (
SELECT 1 FROM TableB
WHERE TableA.Name = TableB.Name 
AND TableA.Color = TableB.Color)
7 голосов
/ 24 июня 2009
SELECT a.Name, a.Color
FROM a LEFT OUTER JOIN b ON (a.Name = b.Name AND a.Color = b.Color)
WHERE b.Name IS NULL AND b.Color IS NULL
4 голосов
/ 24 июня 2009
Select A.Name, A.Color
From A left join B on A.Name = B.Name and A.Color = B.Color
Where B.Name is null
2 голосов
/ 24 июня 2009

Я обычно добавляю столбец «обновленный TIMESTAMP, НЕ ПУСТОЙ, ПО УМОЛЧАНИЮ CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP», и я использую его значение, чтобы проверить, вставлена ​​ли новая строка или изменена существующая.

В приложении, которое я разработал, мне нужно было решить проблему, аналогичную вашей, поэтому я где-то сохранил MAX (обновленный) B, а затем с помощью запроса определил все строки, в которых A.updated> B.updated, и В результате все новые + измененные строки.

Поскольку значением по умолчанию для поля является CURRENT_TIMESTAMP и оно автоматически обновляет «ON UPDATE», вам никогда не придется явно устанавливать его значение.

2 голосов
/ 24 июня 2009

Вы можете использовать оператор EXCEPT, который противоположен UNION. В Oracle эквивалент равен МИНУС.

SELECT * FROM TABLE_A
EXCEPT
SELECT * FROM TABLE_B
2 голосов
/ 24 июня 2009

В SQL Server 2008 вы можете использовать оператор EXCEPT, который используется как UNION, но возвращает все из первого запроса, кроме случаев, когда он также находится во втором:

SELECT * FROM TABLEA EXCEPT SELECT * FROM TABLEB

Я понимаю, что в Oracle есть оператор MINUS, который делает то же самое.

1 голос
/ 24 июня 2009

В Oracle вы, вероятно, будете использовать:

MERGE INTO b USING
  (SELECT name, color 
     FROM a) src 
 ON (src.name = b.name AND color = src.color)
 WHEN NOT MATCHED THEN 
    INSERT (name, color)
    VALUES (src.name, src.color);

Если ваша таблица имеет первичный ключ (у вас действительно есть таблицы без такового?), Например, NAME, и вы хотите вставить или обновить, в зависимости от наличия записи в таблице B, вы должны использовать:

MERGE INTO b USING 
  (SELECT name, color 
     FROM a) src 
  ON (src.name = b.name) 
  WHEN NOT MATCHED THEN 
    INSERT (name, color)
    VALUES (src.name, src.color) 
  WHEN MATCHED THEN 
    UPDATE 
    SET color = src.color; 

Я так понимаю, что в SQL Server также есть оператор MERGE или аналогичный.

1 голос
/ 24 июня 2009

Уже есть много правильных ответов, но я хочу поднять философский вопрос:

Действительно ли эта схема базы данных жизнеспособна в производственной среде внутри одной схемы?

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

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

1 голос
/ 24 июня 2009

Подзапрос NOT EXISTS должен преобразовываться во внешнее соединение:

SELECT Name, Color
FROM TableA
WHERE NOT EXISTS (
  SELECT 1
  FROM TableB
  WHERE TableA.Color = TableB.Color
  AND   TableA.Name  = TableB.Name
)

Или вы можете просто использовать внешнее соединение напрямую:

SELECT TableA.Name, TableA.Color
FROM TableA
LEFT OUTER JOIN TableB
  ON  TableA.Name  = TableB.Name
  AND TableA.Color = TableB.Color
WHERE TableB.Name IS NULL

Они должны быть одинаково эффективными; это вопрос, который вы считаете более интуитивным.

0 голосов
/ 24 июня 2009
INSERT INTO B 
SELECT a.Name, a.Color
FROM A a
LEFT JOIN B b ON a.Name = b.Name AND a.Color = b.Color
WHERE b.Color IS NULL AND b.Name IS NULL
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...