2012-03-16 2 views
0

у меня есть две таблицы, A и B, в Oracle:Удаление таблицы в Oracle с WHERE условие в других таблицах

A (a1, a2) 

    B (b1, b2, b3, b4, b5) 

И некоторые строки, как:

A(type1, 192.168.94.1) 
    A(type1, 192.168.94.2) 
    A(type2, 192.168.94.1) 

    B(type1, 192, 168, 94, 1) 
    B(type1, 192, 168, 94, 3) 
    B(type2, 192, 168, 94, 2) 

В таблице А, есть A (type1, 192.168.94.1)

В таблице В, но также B (type1, 192, 168, 94, 1)

В таблице А, я хочу удалить строку

A(type1, 192.168.94.1) 

Поскольку его тип, как тип в таблице B

A.a1 = B.b1 
    -> type1 = type1 

и адрес IP-дубликат при конкатенации в B

A.a2 = B.b2 ||'.'|| B.b3 ||'.'|| B.b4 ||'.'|| B.5 
    -> 192.168.94.1 = 192.168.94.1 

Не могли бы вы дать мне совет?

+0

Пробуйте код, который я вам дал после того, как вы отредактировали свой вопрос и лучше объяснили, чего вы хотели достичь. Также не просто говорите «не работает», предоставляя сообщения об ошибках или по какой причине он не достиг того, чего вы хотели. – Ollie

+1

Если честно, я бы просто отбросил таблицу 'a' или таблицу' b'. Они вам не нужны, поскольку они, похоже, хранят одни и те же данные. – Ben

+0

@Ben: Это исправление дефекта, поэтому я не могу отказаться от таблицы a. Я хочу удалить некоторые устаревшие строки. – Tuan

ответ

2
delete from A 
where ROWID in 
    (select A.ROWID 
    from A,B 
    where A.A1 = B.B1 
    and A.A2 = concat(B.B2, B.B3, B.B4) 
    ) 
+0

хорошее использование ROWID, но я бы склонен использовать синтаксис SQL-92, а не старый SQL-86 для условия соединения - YMMV. – Ollie

+0

@turbanoff Большое спасибо. Готово. – Tuan

+0

Это решение также лучше, чем WHERE EXISTS, потому что это решение использует индексы. Я сравнил план объяснения для WHERE EXISTS и этого решения ROWID. В случае WHERE EXISTS было выполнено полное сканирование таблицы. –

0

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

DELETE FROM a 
WHERE EXISTS 
     (SELECT 1 
     FROM B 
     WHERE a.a1 = b.b1 
      AND a.a2 = CONCAT(b.b2, b.b3, b.b4)); 

Предположение :

1) связь между таблицей A и B правильна в исходном сообщении
2) Вы только желая, чтобы удалить записи из таблицы A

Надеются, что это помогает ...

EDIT: После ваших новых комментариев вопроса еще мрачнее. Я не знаю, хотите ли вы удалять только данные столбца IP или дублированные строки из таблицы A.

Если вы хотите просто удалить повторяющиеся строки из таблицы A, то это просто:

DELETE FROM A 
WHERE rowid NOT IN 
      (SELECT MIN(rowid) 
       FROM A 
       GROUP BY a1, a2); 

Это предполагает, что столбцы a1 и a2 ваш первичный ключ для таблицы A.

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

+0

Привет, Олли, ваш оператор sql удаляет целые строки. Я только что добавил несколько примеров выше. Заранее спасибо. – Tuan

+0

Чтобы быть справедливым, в вашем вопросе указывалось, что вы хотите удалить всю строку. После редактирования это все равно. Вы хотите удалить только повторяющиеся строки в таблице 'A', где есть ссылка на таблицу' B'? – Ollie

+0

Да, я хочу удалить только. Я только что отредактировал скрипт в своем коде, как вы посоветовали, но он все еще не работает. – Tuan

0

Я подозреваю, что вы ничего не найдя, чтобы удалить, потому что вы не можете быть соединения двух таблиц правильно, потому что ваш CONCAT даст вам concat('192', '168', '94', '1') = '192168941', которая отличается от '192.168.94.1'

delete from A a 
where exists (
    select 1 
    from B b 
    where a.a1 = b.b1 
     and a.a2 = b.b2 || '.' || b.b3 || '.' || b.b4 || '.' || b.b5) 

EDIT :

Использование concat для конкатенации девяти параметров привело к исключению too many parameters, поэтому вместо этого я использую оператор ||.

+0

Я редактировал код. Спасибо – Tuan

+0

Вы пробовали инструкцию SQL, которую я предоставил? – beny23

+0

@ beny23, см. Мой ответ и комментарий след. Я не думаю, что OP фактически хочет связать из таблицы 'A' с' B' вообще. Совсем немного, что на самом деле спрашивается. – Ollie

0

Я пришел из мира SQL Server, поэтому я попытался это:

delete 
from E_CRM_ACTIVITYPOINTER ap 
    inner join tmp_activitypointer_for_delete d 
     on AP.ACTIVITYID = d.activityid 
where ap.current_flag = 1 
    and d.start_date != AP.START_DATE 

Это не работает в моей среде Oracle 11g, поэтому я изменил к этому:

delete 
from E_CRM_ACTIVITYPOINTER 
where (ACTIVITYID,START_DATE) in 
    (
    select AP.ACTIVITYID, AP.START_DATE 
    from E_CRM_ACTIVITYPOINTER ap 
     inner join tmp_activitypointer_for_delete d 
     on AP.ACTIVITYID = d.activityid 
    where ap.current_flag = 1 
     and d.start_date != AP.START_DATE 
    ) 

Надеюсь, это поможет кому-то другому.

Смежные вопросы