2016-03-15 3 views
0

В моем коде я пытаюсь вставить данные в цикл for на основе номера строки. Причина, по которой я хочу использовать его, заключается в том, что в противном случае я получаю ошибку «однострочный подзапрос возвращает более одной строки», потому что мои подзапросы select возвращают более одной строки, и я, очевидно, хочу вставить ее по одному.Вставить строки с помощью ROWNUM В Oracle

declare 
begin 
for x in (select * from PilotKeyLookup) loop 
if x.p2id != null then 
insert into BridgeTable (groupid, pilotid) values (sqBridgeGroupID.nextval, (select p1id from PilotKeyLookup)); 
insert into BridgeTable (groupid, pilotid) values (sqBridgeGroupID.currval, (select p2id from PilotKeyLookup)); 
else 
insert into BridgeTable (groupid, pilotid) values (sqBridgeGroupID.nextval, (select p1id from PilotKeyLookup)); 
end if; 
end loop; 
end; 

И это, как я пытаюсь использовать ROWNUM:

declare 
begin 
for x in (select * from PilotKeyLookup) loop 
if x.p2id != null then 
insert into BridgeTable (groupid, pilotid) values (sqBridgeGroupID.nextval, (select p1id from PilotKeyLookup where rownum = x)); 
insert into BridgeTable (groupid, pilotid) values (sqBridgeGroupID.currval, (select p2id from PilotKeyLookup where rownum = x)); 
else 
insert into BridgeTable (groupid, pilotid) values (sqBridgeGroupID.nextval, (select p1id from PilotKeyLookup where rownum = x)); 
end if; 
end loop; 
end; 

Однако, я получаю «выражение неправильного типа» ошибка. Любые предложения?

ответ

1

Вы, вероятно, нужно условную вставку INSERT ... WHEN ... THEN, как это:

CREATE TABLE PilotKeyLookup(
    p1id int, p2id int 
); 

INSERT INTO PilotKeyLookup VALUES(5, null); 
INSERT INTO PilotKeyLookup VALUES(6, 7); 

CREATE TABLE BridgeTable(
    groupid int, pilotid int 
); 

CREATE SEQUENCE sqBridgeGroupID; 

INSERT 
    WHEN 1 = 1 THEN INTO BridgeTable(groupid, pilotid) 
        VALUES (sqBridgeGroupID.nextval, p1id) 
    WHEN p2id is not null THEN INTO BridgeTable(groupid, pilotid) 
        VALUES (sqBridgeGroupID.currval, p2id) 
SELECT * 
FROM PilotKeyLookup p; 



select * from BridgeTable; 

    GROUPID PILOTID 
---------- ---------- 
     1   5 
     2   6 
     2   7 
+0

Это приятное решение! –

+0

Спасибо, он работал как шарм. Я решил выбрать это решение, потому что он работал быстрее, чем тот, который приведен ниже. – Istvan

0

Есть две проблемы в коде

1) использовать x.p1id вместо подзапроса и

2) жаль, что это x.p2id != null не работает ... ** НЕ НЕВОЗМОЖНО * s'must использовать!

Это работает ...

declare 
begin 
for x in (select * from PilotKeyLookup) loop 
if x.p2id is not null then 
insert into BridgeTable (groupid, pilotid) values (sqBridgeGroupID.nextval, x.p1id); 
insert into BridgeTable (groupid, pilotid) values (sqBridgeGroupID.currval, x.p2id); 
else 
insert into BridgeTable (groupid, pilotid) values (sqBridgeGroupID.nextval, x.p1id); 
end if; 
end loop; 
end; 

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

В качестве exersize вы можете сравнить выполнение двух подходов с некоторыми нетривиальными данными, и вы поймете, почему это хорошая идея избежать цикла (если это возможно).

+0

Спасибо, это сработало, но я выбрал решение выше без цикла, потому что это, казалось, работало быстрее. – Istvan

+0

Это окончательно правильный выбор. Я только документировал, как ** не делать этого ** правильно ... –

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