2013-04-24 3 views
2

Я хочу выбрать все строки, которые существуют в конкретной таблице, и не существует в другой таблице, чтобы удалить их.Удалить данные, которые существуют в одной таблице и не существуют в другой?

Я пишу следующий запрос, но я получаю строки в обеих таблицах!

SELECT UNIQUE b.values_key FROM request_fo a INNER JOIN rm_trans b 
ON b.values_key != a.req_year || ',' || a.req_ser 
AND b.taskcode = 19 
AND b.values_key IS NOT NULL 
AND a.req_year IS NOT NULL 
AND a.req_ser IS NOT NULL 

Я хочу использовать следующее для удаления существуют данные в request_fo и не существует в rm_trans:

DELETE request_fo 
FROM request_fo a 
INNER JOIN 
rm_trans b 
ON b.values_key != a.req_year || ',' || a.req_ser 
AND b.taskcode = 19 
AND b.values_key IS NOT NULL 
AND a.req_year IS NOT NULL 
AND a.req_ser IS NOT NULL 

Правильно ли это ??

+2

Различные СУБД имеют различный синтаксис для операций DELETE, особенно DELETE с операциями объединения. Вы не можете автоматически ожидать, что работает в MS SQL Server для работы в Oracle, DB2, Informix, MySQL, PostgreSQL - обычно это не обязательно работает в Sybase. –

+0

@JonathanLeffler: Тогда, пожалуйста, что синтаксис сделать 'УДАЛЕНИЯ ИЗ request_fo в LEFT JOIN rm_trans B ON b.values_key = a.req_year + '' + a.req_ser И b.taskcode = 19 где Ь. values_key IS NULL; 'in informix –

ответ

2

Вы должны думать в наборах, когда хотите выполнить этот вид операции. Вы используете !=, когда вам нужно NOT IN (...) или NOT EXISTS (...).

Ваша статья b.values_key != a.req_year || ',' || a.req_ser сравнивает каждый ряд от a с каждой строкой в ​​b. В большинстве случаев они не будут приравниваться. Но будет много примеров, когда values_key в этой конкретной строке соответствует a.req_year || ',' || a.req_ser в других строках a, чем тот, который в настоящее время сравнивается. Вот почему вы получаете возвращаемые данные, которые существуют в обеих таблицах.

Вы хотите попробовать что-то вроде этого:

DELETE FROM a 
    WHERE NOT EXISTS (SELECT 1 FROM b 
        WHERE b.values_key = a.req_year || ',' || a.req_ser 
         AND b.task_code = 19) 

Вы также должны работать, что, как SELECT * FROM a WHERE NOT EXISTS (...) проверить его первым. Я бы.

1

Вот синтаксис T-SQL, чтобы сделать так:

Использование LEFT JOIN вместо с b.values_key IS NULL предиката в предложении WHERE и использовать псевдоним a вместо имени таблицы в DELETE пункте:

DELETE a 
FROM request_fo a 
LEFT JOIN rm_trans b ON b.values_key = a.req_year + ',' + a.req_ser 
         AND b.taskcode = 19 
WHERE b.values_key IS NULL; 

в действии здесь:

Предполагая, что req_ser и req_year имеют строку типа данных, если они целые, их отличает.


Как это работает?

LEFT JOIN будет включать в себя те несоответствующие строки из первой таблицы request_fo, которая находится на левой стороне LEFT JOIN, даже если там нет записей удовлетворяют JOIN consition, и в этом случае значение values_key будет NULL для тех несовпадающих строк ,

Например, см this demo, то 2013 4 из первой таблицы не существует во второй таблице поэтому его values_key будет NULL, так что добавление WHERE b.values_key IS NULL даст вам те, которые можно найти в таблице кулака и не нашли в вторая таблица.

+0

зачем устанавливать' b.values_key IS NULL'?! –

+0

не принимает этот синтаксис в 'informix' –

5

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

delete from t1 
where t1 = something 
and not exists 
(
    select 1 
    from t2 
    where t1.key = t2.key 
) 
Смежные вопросы