database.sarang.net
UserID
Passwd
Database
DBMS
MySQL
ㆍPostgreSQL
Firebird
Oracle
Informix
Sybase
MS-SQL
DB2
Cache
CUBRID
LDAP
ALTIBASE
Tibero
DB 문서들
스터디
Community
공지사항
자유게시판
구인|구직
DSN 갤러리
도움주신분들
Admin
운영게시판
최근게시물
PostgreSQL Q&A 9819 게시물 읽기
No. 9819
잘되던 함수가...
작성자
알려줘요
작성일
2017-05-17 09:27ⓒ
2017-05-17 10:51ⓜ
조회수
10,104

 안녕하세요. 현업에서 PostgreSQL 을 이용하여 시스템을 유지관리 하고 있는 사용자 입니다.

잘 사용하던 함수가  일부 제대로 작동되지않아 분석을 하는도중  전부 똑같은 현상을 보이더군요.

ERROR: 쿼리에 결과 데이터의 대상이 없음
HINT: SELECT의 결과를 취소하려면 대신 PERFORM을 사용하십시오.
CONTEXT:  PL/pgSQL 함수 "indigo.fn_04_tb_bsi_hc_blk_m()" 의 145번째 SQL 문

********** Error **********
ERROR: 쿼리에 결과 데이터의 대상이 없음
SQL state: 42601
Hint: SELECT의 결과를 취소하려면 대신 PERFORM을 사용하십시오.

 위와 같은 에러를 내뿜고는 insert  나 update 도중  스톱이 되어버립니다.  관련 테이블들 index 재작성, vacum 실행등을 해봐도..들어가가 에러가 발생합니다.
 들어가는 데이터는 실행할때 마다 틀립니다. 실행하다보면 정상적으로 작동할떄도 있습니다. ㅡㅡ;; 이런 현상은 당최 외그럴까요..
 

------------------------------함수는 다음과 같이 작성하였습니다.

 

CREATE OR REPLACE FUNCTION indigo.fn_02_tb_bsi_bzdt_m()

  RETURNS numeric AS

$BODY$

DECLARE

V_SEQ_NO   NUMERIC := 0;

V_START_DT VARCHAR;

V1         RECORD;

V2         RECORD;

V_IS_CNT   NUMERIC := 0;

V_DEL_IDX  NUMERIC := 0;

V_DEL_CNT  NUMERIC := 0;

V_INS_IDX  NUMERIC := 0;

V_INS_CNT  NUMERIC := 0;

V_TOT_CNT  NUMERIC := 0;

V_GEO_CNT  NUMERIC := 0;

QUERY_STR  VARCHAR;

LPPA_CBND  VARCHAR;

V_TYPE     VARCHAR;

BEGIN

 

/* BSI_사업지구_기본 */

/* Data Log 번호 조회 */

SELECT SEQ_NO INTO V_SEQ_NO FROM 테이블 WHERE TABLE_NM = '테이블이름';

 

/* 시작일시 */

SELECT TO_CHAR(SYSDATE, 'YYYYMMDDHH24MISS') INTO V_START_DT FROM DUAL;

 

/* 삭제 레코드 수 */

SELECT COUNT(*) INTO V_DEL_CNT FROM 테이블 WHERE EAI_CNNT_DS_CD = 'D';

 

/* 입력 레코드 수 */

SELECT COUNT(*) INTO V_INS_CNT FROM 테이블 WHERE EAI_CNNT_DS_CD <> 'D';

 

RAISE NOTICE '테이블명 : BSI_사업지구_기본';

RAISE NOTICE '총 삭제건수 : %', V_DEL_CNT;

RAISE NOTICE '총 입력건수 : %', V_INS_CNT;

 

RAISE NOTICE '삭제시작 !';

 

/* 연계 데이터 조회 - 삭제 */

FOR V1 IN SELECT 컬럼,

컬럼1,...

           FROM 테이블

          WHERE EAI_CNNT_DS_CD IN('D')

LOOP

 

/* 삭제처리 */

DELETE

   FROM 테이블

  WHERE BZDT_CD = V1.BZDT_CD;

 

V_DEL_IDX := V_DEL_IDX + 1;

RAISE NOTICE '삭제처리 : %', V_DEL_IDX || '/' || V_DEL_CNT;

 

END LOOP;

 

RAISE NOTICE '삭제종료 !';

RAISE NOTICE '입력시작 !';

 

/* 연계 데이터 조회 - 삭제 외 */

FOR V2 IN SELECT 컬럼

               ,컴럼1...

           FROM 테이블

          WHERE EAI_CNNT_DS_CD <> 'D'

ORDER BY EAI_CNNT_NO

 

LOOP

 

/* 데이터 존재여부 체크 */

SELECT COUNT(*)

 INTO V_IS_CNT

   FROM 테이블

  WHERE BZDT_CD = V2.BZDT_CD;

 

 /* 수정처리 */

 IF V_IS_CNT > 0 THEN

 

UPDATE 테이블

      SET 컬럼 = V2.컬럼 ...

    WHERE 컬럼 = V2.컬럼;

 

V_INS_IDX := V_INS_IDX + 1;

V_TYPE    := 'U';

 

 /* 입력처리 */

 ELSE

 

INSERT

 INTO 테이블(컬럼,...)VALUES (V2.컬럼,...);

 

V_INS_IDX := V_INS_IDX + 1;

V_TYPE    := 'I';

 

END IF;

 

RAISE NOTICE '입력처리 : %', V_INS_IDX || '/' || V_INS_CNT || ' (' || V_TYPE || ')';

 

END LOOP;

 

RAISE NOTICE '입력종료 !';

 

/* 전체 처리 개수 */

SELECT COUNT(*)

 INTO V_TOT_CNT

 FROM 테이블;

 

/* 처리 로그 기록 */

UPDATE 테이블

  SET 컬럼 = V_START_DT

     ,컬럼1 = TO_CHAR(SYSDATE, 'YYYYMMDDHH24MISS')

     ,컬럼2 = V_INS_CNT

     ,컬럼3 = V_DEL_CNT

     ,컬럼4 = V_TOT_CNT

WHERE 컬럼5 = V_SEQ_NO;

 

RETURN V_TOT_CNT;

 

/* 에러처리 */

EXCEPTION

 

/* 중복에러 */

WHEN DUP_VAL_ON_INDEX

THEN SELECT indigo.FN_SAVE_DATA_ERROR_LOG(V_START_DT, V_SEQ_NO);

 

/* 그밖의 에러 */

WHEN OTHERS

THEN SELECT indigo.FN_SAVE_DATA_ERROR_LOG(V_START_DT, V_SEQ_NO);

 

END;

$BODY$

  LANGUAGE plpgsql VOLATILE

  COST 100;

ALTER FUNCTION indigo.fn_02_tb_bsi_bzdt_m()

  OWNER TO indigo;

 

 

 

---------------------------------------------------------------------------------------------------------

이 글에 대한 댓글이 총 10건 있습니다.

에러만 보면

select 한 것에 대한 결과값을 저장해주는 부분에 대한 into절이 빠져서 그런걸로 보여집니다.

index나 vacuum은 논외겠죠..로직상 문제니

데이터에 따른 것은 문제 로직에 들가냐 안들가냐 그 차이일거라 예상됩니다.

올려주신게 postgresql community version이신건가요..

sysdate나 dual테이블이 있는게 ..음

김주왕(kimjuking)님이 2017-05-17 10:06에 작성한 댓글입니다.
이 댓글은 2017-05-17 10:08에 마지막으로 수정되었습니다.

postgresql 은 9.5 를 사용중입니다.
로직상의 문제라면 아예 안되야하는데 잘될때는 똑같은 분기를 타고 잘되니까요. 
예를 들어 insert 를 타는조건이라면 에러가 난다 update 를 타면 에러가 난다..이런게 아닙니다.
그냥 인서트되다 중간에 에러 update 되다 중간에 에러...전체데이터가 1천줄이라면 실행할때마다

30줄 에서 에러, 10줄에서 에러.. 이런식으로 매번 실행건수가 다르다가  에러때문에 스톱이 되는현상입니다.

정확하게 어디에서 빠진거라고 말씀하시는건지..혹시 FOR부분이라면..;
FOR 부분은 반복문부분이라 FOR   IN이 맞을껍니다. LOOP 안쪽 INSERT 라면..INTO 는 존제합니다.
삭제하다가..빠진듯.

으아~님이 2017-05-17 10:23에 작성한 댓글입니다.
이 댓글은 2017-05-17 10:30에 마지막으로 수정되었습니다. Edit

postgresql인데 sysdate나 dual이 있는건 orafce 모듈을 사용하시는건가요..이건 뭐 중요하진 않겠지만

전체 펑션을 확인할수가 없기에 정확한 분석은 힘들고 올려주신 에러 부분에 대한 답은

결과값을 받는데 그거에 대한 처리로직이 없을 경우에 발생하는 에러인데

올려주신 부분만 봐서는 그부분에 대한 내용이 삭제된거 같습니다.

김주왕(kimjuking)님이 2017-05-17 10:39에 작성한 댓글입니다.

 PAS9.5 EDB 입니다. Extensions 은

adminpack,
dblink,
edb_dblink_libpq,
edb_dblink_oci,
edbspl,
fuzzystrmatch,
mysql_fdw,
oracle_fdw,
pldbgapi,
plpgsql,
postgis,
postgres_fdw 입니다.

쿼리는 좀더 자세하게..수정하였습니다. 

으아~님이 2017-05-17 10:57에 작성한 댓글입니다. Edit

예외처리시에

 

THEN SELECT indigo.FN_SAVE_DATA_ERROR_LOG(V_START_DT, V_SEQ_NO);

 

이 펑션의 output이 어떻게 되어있나요

 

output이 있다면

THEN SELECT indigo.FN_SAVE_DATA_ERROR_LOG(V_START_DT, V_SEQ_NO)

into output1;

 

이런식이거나 없다면

 

THEN perform indigo.FN_SAVE_DATA_ERROR_LOG(V_START_DT, V_SEQ_NO);

 

이 부분이 문제일걸로 예상됩니다.

김주왕(kimjuking)님이 2017-05-17 11:31에 작성한 댓글입니다.

 

해당부분은 단순 update 를 실행하는건대요 리턴타입은 void 리턴이 없는것..입니다. 없다면 perform 을 써야하는건가요?

CREATE OR REPLACE FUNCTION indigo.fn_save_data_error_log( i_start_dt character varying, i_seq_no numeric) RETCREATE OR REPLACE FUNCTION indigo.fn_save_data_error_log(

    i_start_dt character varying,
    i_seq_no numeric)
  RETURNS void AS
$BODY$
BEGIN
 
/* 로그기록 */
UPDATE 테이블
SET START_DT = $1
,END_DT = TO_CHAR(SYSDATE, 'YYYYMMDDHH24MISS')
,DATA_RESULT = 'F'
WHERE SEQ_NO = $2;
 
END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION indigo.fn_save_data_error_log(character varying, numeric)

  OWNER TO indigo;

으아~님이 2017-05-17 12:32에 작성한 댓글입니다. Edit

return값이 없다면 perform을 쓰는게 맞습니다.

김주왕(kimjuking)님이 2017-05-17 12:42에 작성한 댓글입니다.

말씀하신부분 을

/* 에러처리 */
EXCEPTION
 
/* 중복에러 */
WHEN DUP_VAL_ON_INDEX
THEN perform indigo.FN_SAVE_DATA_ERROR_LOG(V_START_DT, V_SEQ_NO);
 
/* 그밖의 에러 */
WHEN OTHERS
THEN perform indigo.FN_SAVE_DATA_ERROR_LOG(V_START_DT, V_SEQ_NO);
로 바꿔서 실행하였더니 다른에러가 ;ㅁ;

 ERROR:  컨트롤이 RETURN 없이 함수 끝에 도달함

CONTEXT:  PL/pgSQL 함수 indigo.fn_02_tb_bsi_bzdt_m()
********** Error **********
 
ERROR: 컨트롤이 RETURN 없이 함수 끝에 도달함
SQL state: 2F005
Context: PL/pgSQL 함수 indigo.fn_02_tb_bsi_bzdt_m()
 
EXCEPTION 에서 리턴을 다시 해주니까..정상적으로 돌긴합니다.
으아님이 2017-05-17 12:50에 작성한 댓글입니다.
이 댓글은 2017-05-17 13:01에 마지막으로 수정되었습니다. Edit

예외처리 밑에 return을 하면 될거 같습니다.

김주왕(kimjuking)님이 2017-05-17 12:57에 작성한 댓글입니다.

김주왕님 답변 감사합니다.  덕분에 비지니스상에 문제생길수 있는
부분이 해결이 되었네요. 다른원인이 있는거 같습니다.

으아~님이 2017-05-17 13:16에 작성한 댓글입니다. Edit
[Top]
No.
제목
작성자
작성일
조회
9822ora2pg 사용법 [3]
postgres
2017-05-18
8786
98219.6.3 released
전상도
2017-05-18
7265
9820아래 잘되던함수 해결하였습니다. [1]
알려드림
2017-05-17
8365
9819잘되던 함수가... [10]
알려줘요
2017-05-17
10104
9816pgpool2 failover 오류..
김솔지
2017-05-16
7489
9815외부 이중화 솔루션 사용 중 문제발생. [1]
이정재
2017-05-15
8145
9809pgpool2 failover 체크 [1]
김솔지
2017-05-12
8387
Valid XHTML 1.0!
All about the DATABASE... Copyleft 1999-2024 DSN, All rights reserved.
작업시간: 0.019초, 이곳 서비스는
	PostgreSQL v16.4로 자료를 관리합니다