SQL - вставить в таблицу, если значение существует в другой таблице

Я пытаюсь заставить SQL-запрос ниже работать, но я получаю сообщение об ошибке, моя проблема заключается в следующем:

Мне нужно перебрать набор результатов из оператора select (эта часть в порядке). Внутри цикла для каждой строки мне нужно проверить, существует ли URL-адрес в таблице A. Если это так, вставьте сопоставление в таблицу B, в противном случае вставьте новую строку в таблицу C.

Это то, что у меня есть, но когда я пытаюсь выполнить, я получаю сообщение об ошибке в строке с IF, говорящим ORA-06550: строка 8, столбец 15: PLS-00103: обнаружен символ «ВЫБОР» при ожидании одного из следующих :( - + кейс мод новый нет.....

DECLARE 
STANDARD_LINK_ID TABLEB.LINK_ID%type;

BEGIN   
      FOR LINK_ROW IN ( SELECT LINKTEXT, LINKURL, CORPID FROM OLD_DATA)
      LOOP
          IF (SELECT COUNT(URL) FROM TABLEA WHERE URL = LINK_ROW.LINKURL) = 1
          THEN
            SELECT LINKID INTO STANDARD_LINK_ID FROM TABLEA WHERE URL = LINK_ROW.URL;
            INSERT INTO TABLEB(LINK_ID, CORP_ID) 
            VALUES (STANDARD_LINK_ID,  LINK_ROW.CORPID);
          ELSE
            INSERT INTO TABLEB(LINK_ID, LINK_NAME, URL, CORP_ID) 
            VALUES (SEQ_LINK.NEXTVAL, LINK_ROW.LINKTEXT, LINK_ROW.LINKURL, 
                                 LINK_ROW.CORP_ID);
          END IF;                 
      END LOOP;
    COMMIT;
END;

person Kaskade    schedule 02.12.2011    source источник


Ответы (3)


Я видел, как это делается таким образом; но не выбор с возвращаемым значением, встроенным в условие

https://forums.oracle.com/forums/thread.jspa?threadID=177035

DECLARE 
STANDARD_LINK_ID TABLEB.LINK_ID%type;
DECLARE W_LINK_COUNT NUMBER (1,0);

BEGIN   
      FOR LINK_ROW IN ( SELECT LINKTEXT, LINKURL, CORPID FROM OLD_DATA)
      LOOP
          SELECT COUNT(URL) INTO W_LINK_COUNT FROM TABLEA WHERE URL = LINK_ROW.LINKURL;
          IF  W_LINK_COUNT = 1
          THEN
            SELECT LINKID INTO STANDARD_LINK_ID FROM TABLEA WHERE URL = LINK_ROW.URL;
            INSERT INTO TABLEB(LINK_ID, CORP_ID) 
            VALUES (STANDARD_LINK_ID,  LINK_ROW.CORPID);
          ELSE
            INSERT INTO TABLEB(LINK_ID, LINK_NAME, URL, CORP_ID) 
            VALUES (SEQ_LINK.NEXTVAL, LINK_ROW.LINKTEXT, LINK_ROW.LINKURL, 
                                 LINK_ROW.CORP_ID);
          END IF;                 
      END LOOP;
    COMMIT;
END;
person xQbert    schedule 02.12.2011

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

DECLARE 
STANDARD_LINK_ID TABLEB.LINK_ID%type;
URL_COUNT NUMBER(10);

BEGIN   
      FOR LINK_ROW IN ( SELECT LINKTEXT, LINKURL, CORPID FROM OLD_DATA)
      LOOP
          SELECT COUNT(URL) INTO URL_COUNT FROM TABLEA WHERE URL = LINK_ROW.LINKURL;
          IF URL_COUNT = 1 THEN
            SELECT LINKID INTO STANDARD_LINK_ID FROM TABLEA WHERE URL = LINK_ROW.URL;
            INSERT INTO TABLEB(LINK_ID, CORP_ID) 
            VALUES (STANDARD_LINK_ID,  LINK_ROW.CORPID);
          ELSE
            INSERT INTO TABLEB(LINK_ID, LINK_NAME, URL, CORP_ID) 
            VALUES (SEQ_LINK.NEXTVAL, LINK_ROW.LINKTEXT, LINK_ROW.LINKURL, 
                                 LINK_ROW.CORP_ID);
          END IF;                 
      END LOOP;
    COMMIT;
END;

Надеюсь, это поможет вам понять, в чем проблема.

person Klaus Byskov Pedersen    schedule 02.12.2011

Я написал это очень быстро, но я думаю, что эти два запроса решат вашу проблему без цикла (который медленнее, чем однократная вставка):

-- insert to tableb when exists in tablea
insert into tableb(link_id, corp_id) 
select a.linkid, o.corpid
from old_data o
join tablea a on o.url = a.url


-- insert to tablec when not exists in tablea
insert into tablec(link_id, link_name, url, corp_id) 
select seq_link.nextval, o.linktext, o.linkurl, o.corp_id
from old_data o
where not exists(select 1 from tablea a where o.url = a.url)

пс. ты не забыл про tablec в else?

person Michał Powaga    schedule 02.12.2011
comment
Теперь я из другого мира, но если это похоже на мой мир, операции набора выполняются намного быстрее, чем циклы. Не знаю, верно ли это и для оракула, поэтому, пожалуйста, не стесняйтесь просветить меня. - person Asken; 02.12.2011
comment
Я думаю, что loop в мире SQL - это какое-то зло, особенно когда есть способ сделать это, используя наборы результатов со многими записями за одно обращение (как в этом случае). - person Michał Powaga; 02.12.2011
comment
+1 Я согласен с тем, что производительность и избежание циклов - это, как правило, хорошо. - person xQbert; 02.12.2011
comment
в этом случае запрос просто используется для копирования данных один раз, поэтому, к счастью, производительность не является проблемой. - person Kaskade; 02.12.2011