프로시져의 다중 커서 이용시 에러 0 5 4,656

by tae [PL/SQL] [2011.08.31 09:11:33]



안녕하세요? 현재 프로젝트 진행중에 다중 커서가 들어간 프로시져를 개발중입니다.

근데 아래 프로시져를 생성하려하는데
ORA-02067 트랜잭션 또는 저장점 롤백이 요구됩니다 라는 에러가 뜹니다. 도움을 요청드립니다. 

CREATE OR REPLACE PROCEDURE sp_jde_inbound IS

v_cust_po  O_ORDER_CONFIRM_H.cust_po%TYPE;
CURSOR c_order_H IS

  SELECT
    H.CUST_PO,
    H.CUST_CD,
    SHIPTO_CD,
    lPad(company_cd,12) MCU,
    Decode(company_cd,'275', '95600', '300', '95600', '95601') SAUPJANG,
    ( SELECT julian_dt FROM o_date  WHERE yyyymmdd = REQUEST_DT) REQUEST_DT,
    --( SELECT julian_dt FROM o_date  WHERE yyyymmdd = PICKING_DT) PICKING_DT,
    ( SELECT julian_dt FROM o_date  WHERE yyyymmdd = To_char(To_Date(SubStr(confirm_dt,1,10)),'YYYYMMDD') ) CONFIRM_DT,
    ( SELECT julian_dt FROM o_date WHERE yyyymmdd = To_Char(SYSDATE, 'yyyymmdd') ) TODAY,
    ( SELECT To_Char(SYSDATE,'hh24miss') FROM dual ) TIME,
    H.REQUEST_TIME,
    H.ADD1 || H.ADD2 AS ADDR,
    H.CUSTOMMATTER,
    H.RECEIVER,
    H.TEL1 || '/' || H.TEL2 AS TEL,
    H.REMARK,
    H.ZIP_CD
  FROM
    O_ORDER_CONFIRM_H H
  WHERE interface_dt IS NULL;
CURSOR c_order_D IS
    SELECT
  H.CUST_PO,
  H.CUST_CD,
  SHIPTO_CD,
  lPad(company_cd,12) MCU,
  Decode(company_cd,'275', '95600', '300', '95600', '95601') SAUPJANG,
  LINE_NO,
  ITEM_CD,
  UNIT,
  QUANTITY,
  PRICE,
  ( SELECT julian_dt FROM o_date  WHERE yyyymmdd = REQUEST_DT) REQUEST_DT,
  --( SELECT julian_dt FROM o_date  WHERE yyyymmdd = PICKING_DT) PICKING_DT,
  ( SELECT julian_dt FROM o_date  WHERE yyyymmdd = To_char(To_Date(SubStr(confirm_dt,1,10)),'YYYYMMDD') ) CONFIRM_DT,
  ( SELECT julian_dt FROM o_date WHERE yyyymmdd = To_Char(SYSDATE, 'yyyymmdd') ) TODAY,
  ( SELECT To_Char(SYSDATE,'hh24miss') FROM dual ) TIME,
  U.JDEID
    FROM
  O_ORDER_CONFIRM_H H
  INNER JOIN O_ORDER_CONFIRM_D D ON H.CUST_PO = D.CUST_PO
  LEFT OUTER JOIN O_USER U ON D.INSERTID = U.USERID
    WHERE
    D.CUST_PO = v_cust_po;

BEGIN
 FOR c IN c_order_H LOOP
  BEGIN
    v_cust_po := c.CUST_PO;
INSERT INTO test8dta.F47011@LGKDDB
  (
    SYEDSQ,   -- NUMBER 22  Y
    SYEKCO,   -- CHAR 5   Y
    SYEDOC,   -- NUMBER 22  Y
    SYEDCT,   -- CHAR 2   Y
    SYEDLN,   -- NUMBER 22  Y
    SYEDST,   -- CHAR 6   Y
    SYEDDL,   -- NUMBER 22  Y
    SYEDSP,   -- CHAR 1   Y
    SYTPUR,   -- CHAR 2   Y
    SYKCOO,   -- CHAR 5   Y
    SYVR01,   -- CHAR 25    Y
    SYDCTO,   -- CHAR 2   Y
    SYMCU,    -- CHAR 12    Y
    SYAN8,    -- NUMBER 22  Y
    SYSHAN,   -- NUMBER 22  Y
    SYPDDJ,
    SYDRQJ,   -- NUMBER 22 6 Y
    SYTRDJ,   -- NUMBER 22 6 Y
    SYUPMJ,
    SYTDAY
  )
  VALUES
  (
    0,
    C.SAUPJANG,
    ( SELECT Nvl(Max(syedoc),0) + 1 FROM test8dta.F47011@LGKDDB WHERE syedct = 'SZ' ),
    'SZ',
    0,
    '850',
    0,
    ' ',
    '02',
    C.SAUPJANG,
    C.CUST_PO,
    'SO',
    C.MCU,
    C.CUST_CD,
    C.SHIPTO_CD,
    '', --C.PINGKING_DT,
    C.REQUEST_DT,
    C.CONFIRM_DT,
    C.TODAY,
    C.TIME
  );

    INSERT INTO test8dta.F4706@LGKDDB
  (
    ZAEDTY, -- CHAR 1   Y 레코드유형    (default : 6)
    ZAEDSQ, -- NUMBER  22   Y 레코드 순서   (default : 3)
    ZAEKCO, -- CHAR 5   Y 문서 키 회사
    ZAEDOC, -- NUMBER  22   Y 문서 번호
    ZAEDCT, -- CHAR 2   Y 문서유형
    ZAEDLN, -- NUMBER  22   Y 라인 번호
    ZAEDSP, -- CHAR 1   Y 처리 완료(Y/N)
    ZAFILE, -- CHAR    10   Y 파일 ID
    ZADCTO, -- CHAR 2   Y 오더 유형
    ZAKCOO, -- CHAR 5   Y 오더 회사
    ZAANTY, -- CHAR 1   Y 주소 번호 유형 (default : 2)
    ZAAN8,  -- NUMBER  22   Y 주소 번호
    ZAMLNM, -- CHAR    40   Y 우편명    (납품처명)
    ZAADD1, -- CHAR    40   Y 납품주소 (주소1 + 주소2)
    ZAADD2, -- CHAR    40   Y *실제 거래처주의사항 란으로 활용함
    ZACTY1, --  시 인수자
    ZAADD3, -- CHAR    40   Y 전화번호
    ZAADD4, -- CHAR    40   Y 요청사항
    ZAADDZ, -- CHAR    12   Y 우편번호
    ZACOUN, -- CHAR    25   Y 요청시간
    ZACTR,  -- CHAR 3   Y 국가 (default : KR)
    ZAUPMJ, -- NUMBER  22 6 0 Y 갱신 일자
    ZATDAY  -- NUMBER  22   Y 시간
  )
  VALUES
  (
    '6',
    3,
    C.SAUPJANG,
    ( SELECT syedoc  FROM test8dta.F47011@LGKDDB WHERE Trim(SYVR01) =C.CUST_PO AND syedct = 'SZ' ),
    'SZ',
    0,
    ' ',
    'F47011',
    'SO',
    C.SAUPJANG,
    '2',
    C.SHIPTO_CD,
    ( SELECT shipto_nm FROM o_shipto WHERE shipto_cd = C.SHIPTO_CD ),
    C.ADDR,
    C.custommatter,
    C.receiver,
    C.TEL,
    C.remark,
    C.zip_cd,
    C.request_time,
    'KR',
    C.TODAY,
    C.TIME
  );
  ------------------------------------------------------------
  BEGIN
    FOR d IN c_order_D LOOP
  BEGIN
  INSERT INTO test8dta.F47012@LGKDDB
  (
    SZEDSQ,   -- NUMBER    22    Y
    SZEKCO,   -- CHAR    5    Y
    SZEDOC,   -- NUMBER    22    Y
    SZEDCT,   -- CHAR    2    Y
    SZEDLN,   -- NUMBER    22    Y
    SZEDDL,   -- NUMBER    22    Y
    SZEDSP,   -- CHAR    1    Y
    SZKCOO,   -- CHAR    5    Y
    SZDCTO,   -- CHAR    2    Y
    SZLNID,   -- NUMBER    22    Y
    SZMCU,    -- CHAR   12    Y
    SZAN8,    -- NUMBER    22    Y
    SZSHAN,   -- NUMBER    22    Y
    SZPDDJ,
    SZDRQJ,   -- NUMBER    22    Y
    SZTRDJ,   -- NUMBER    22    Y
    SZVR01,   -- CHAR   25    Y
    SZLITM,   -- CHAR   25    Y
    SZUOM,    -- CHAR    2    Y
    SZUORG,   -- NUMBER    22    Y
    SZUPRC,   -- 단가
    SZAEXP,   -- 금액
    SZTORG,   -- 처리요청자(JDE ID를 바인딩함)
    SZUPMJ,   -- 생성일자
    SZTDAY    -- 시간

  )
  VALUES
  (
    0,
    d.SAUPJANG,
    ( SELECT syedoc  FROM test8dta.F47011@LGKDDB WHERE Trim(SYVR01) = d.CUST_PO AND syedct = 'SZ' ), --( SELECT Nvl(Max(SZEDOC),0) + 1 FROM test8dta.F47012@LGKDDB WHERE szedct = 'SZ'),
    'SZ',
    d.LINE_NO,
    0,
    ' ',
    d.SAUPJANG,
    'SO',
    0,
    d.MCU,
    d.CUST_CD,
    d.SHIPTO_CD,
    '', -- PINGKING_DT
    d.REQUEST_DT,
    d.CONFIRM_DT,
    d.CUST_PO,
    d.ITEM_CD,
    d.UNIT,
    d.QUANTITY * 100,
    d.PRICE * 10000,
    d.PRICE,
    d.JDEID,
    d.TODAY,
    d.TIME
  );
   EXCEPTION
    WHEN others THEN
    rollback;
  END; -- line END
    END LOOP;  -- line loop END

    EXCEPTION
  WHEN others THEN
  rollback;
    END; -- header END
  END;
END LOOP;  -- header loop END
  commit;
END; -- Procedure END
/
 
by tae [2011.08.31 10:24:49]
답신 감사드립니다..

제가 이해력이 딸려서 확인 한번 요청드릴께요.. 아래와 같이 하면 된다는 말씀이신지...

);
END LOOP; -- line loop END

EXCEPTION
WHEN others THEN
rollback;
END;



END LOOP; -- header loop END
EXCEPTION
WHEN others THEN
rollback;
END;

commit;

END;
/

by 허재영 [2011.08.31 10:59:14]
이거 제가 잘못 봤네요. 예외처리 위치가 처음에 작성하신게 맞네요.
begin
예외처리
end;
begin end;를 못보고.. for문 안에 begin이 존재하고 그 안에 예외 처리가 존재 하는게 맞습니다.

by 허재영 [2011.08.31 11:00:03]
오류
BEGIN
FOR c IN c_order_H LOOP
BEGIN
v_cust_po := c.CUST_PO;
INSERT INTO test8dta.F47011@LGKDDB

프로시져 내에서 INSERT INTO test8dta.F47011@LGKDDB 이런 구문은 직접 사용이 불가 합니다.

execute immediate 를 사용하시기 바랍니다.




참고로 To_char(To_Date(SubStr(confirm_dt,1,10)),'YYYYMMDD')
confirm_dt 이컬럼 데이터 타입이 뭔가요? 날짜로 변경한다음 문자로 다시 변경하는데요.
날짜 타입이면 To_char(confirm_dt,'YYYYMMDD')
문자 타입이면 SubStr(confirm_dt,1,10) 형변환은 한번이면 될듯 한데요.

confirm_dt가 형변환되어 자주 조인되는 컬럼이면 인덱스 생성시에 함수로 생성 해보시기 바랍니다.
create index 인덱스명 on 테이블명 ( To_char(confirm_dt,'YYYYMMDD') );

by 마농 [2011.08.31 11:30:57]
질문이 중간에 잘렸네요.
begin ~ end 조합과
loop ~ end loop 조합이 정확하게 맞아 떨어지는 지 확인해 보세요.

by tae [2011.08.31 13:53:00]

다행히 조언주셔서 구문 오류는 잡았는데 아래 에러가 뜨네요.ㅠㅠ
-> ORA-02067 트랜잭션 또는 저장점 롤백이 요구됩니다
댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입