2011-03-16 5 views
16

나는 다음과 같은 의사-SQL에 대한 올바른 구문을 알아낼 수 없습니다 :PLSQL 삽입

INSERT INTO some_table 
      (column1, 
      column2) 
    SELECT col1_value, 
      col2_value 
     FROM other_table 
     WHERE ...  
    RETURNING id 
     INTO local_var; 

내가 서브 쿼리의 값으로 뭔가를 삽입하고 싶습니다. 삽입 후 새로운 생성 된 ID가 필요합니다.

Heres는 무엇 오라클 문서는 말한다 :

Insert Statement

Returning Into

내가 대안이 있습니까 ... 그것은 단지 값 절 불가능하다고 생각 OK?

답변

14

INSERT에서 RETURNING BULK COLLECT를 사용할 수 없습니다. 이 방법은 업데이트 작업 및 howeveer 삭제 할 수 있습니다

create table test2(aa number) 
/
insert into test2(aa) 
     select level 
     from dual 
     connect by level<100 
/  

set serveroutput on 
declare 
    TYPE t_Numbers IS TABLE OF test2.aa%TYPE 
     INDEX BY BINARY_INTEGER; 
     v_Numbers t_Numbers; 
     v_count number; 
begin 


update test2 
    set aa = aa+1 
returning aa bulk collect into v_Numbers; 

    for v_count in 1..v_Numbers.count loop 
     dbms_output.put_line('v_Numbers := ' || v_Numbers(v_count)); 
    end loop; 

end; 
당신은이 문서에 설명 된대로 몇 가지 추가 단계 (A FORALL INSERT 이용하여 치료를하고) 작업을 얻을 수

:

returning with insert..select

T

자신이 만든 예제를 활용 TEST2 테스트 테이블에 적용 할 수

CREATE or replace TYPE ot AS OBJECT 
    (aa number); 
/


CREATE TYPE ntt AS TABLE OF ot; 
/

set serveroutput on 
DECLARE 

     nt_passed_in ntt; 
     nt_to_return ntt; 

     FUNCTION pretend_parameter RETURN ntt IS 
      nt ntt; 
     BEGIN 
      SELECT ot(level) BULK COLLECT INTO nt 
     FROM dual 
     CONNECT BY level <= 5; 
     RETURN nt; 
     END pretend_parameter; 

    BEGIN 

     nt_passed_in := pretend_parameter(); 

     FORALL i IN 1 .. nt_passed_in.COUNT 
     INSERT INTO test2(aa) 
     VALUES 
     (TREAT(nt_passed_in(i) AS ot).aa 
     ) 
     RETURNING ot(aa) 
     BULK COLLECT INTO nt_to_return; 

     FOR i IN 1 .. nt_to_return.COUNT LOOP 
     DBMS_OUTPUT.PUT_LINE(
      'Sequence value = [' || TO_CHAR(nt_to_return(i).aa) || ']' 
      ); 
     END LOOP; 

    END; 
/
+0

+1 좋은 예! –

+0

멋지다! 나에게 남은 유일한 문제는 객체 유형을 선언하는 것입니다. 패키지에서 객체 유형을 선언 할 수는 없습니다 ... –

-2

이것은 생각하기에 쉽지는 않지만 MySQL을 사용하는 것만 큼 쉽지는 않습니다. 오라클은 결과를 ping 할 수있는 방식으로 마지막 삽입을 추적하지 않습니다.

ROWID를 사용하여이 작업을 수행 할 수있는 다른 방법이 필요합니다. 그러나 여기에는 함정이 있습니다.

이 링크

문제 논의 : 삽입이 선택을 기반으로하기 때문에 http://forums.oracle.com/forums/thread.jspa?threadID=352627

+0

질문과는 관계가 없습니다. 특정 세션에서 삽입 한 마지막 행을 식별하는 것이 아니라 특정 INSERT 문에서 일련의 값을 반환하는 것이 었습니다. –

0

을, 오라클은 여러 행이 구문을 삽입 허용된다고 가정한다. 이 경우 BULK COLLECT를 사용하여 삽입 된 모든 행의 값을 결과 집합으로 검색해야 함을 보여주기 때문에 반환 절 문서의 여러 행 버전을 살펴보십시오.

결국 삽입 쿼리가 두 개의 행을 만들면 반환 값이 단일 변수에 포함됩니까?

편집 - 생각했던 것처럼 작동하지 않습니다.

+0

나는 그것을 시도했지만 ORA 009333을 얻는다. SQL 명령이 제대로 끝나지 않았다. 컬렉션 유형은 좋은 생각입니다. –

+0

Tony가 대답 한 바에 따르면 BULK COLLECT는 적어도 10g 이전에는 INSERT와 함께 작동하지 않습니다. 이것이 11g에서 바뀌 었는지에 대해서는 명확하지 않습니다. –

+0

예, 나는 이것이 효과가 있다고 생각했지만 그렇지 않은 것으로 보입니다. 나쁜 조언을해서 유감입니다. –

11

불행히도 그건 불가능합니다. RETURNING은 INSERT ... VALUES 문에서만 사용할 수 있습니다. 이 주제에 대한 설명은 this Oracle forum thread을 참조하십시오.

+0

+1 정확함에 대해 –