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 4497 게시물 읽기
No. 4497
Trigger에서 이상한 현상??
작성자
이승철
작성일
2002-12-26 17:27
조회수
1,223

초보 디비사용자 입니다.

Trigger를 사용하려고 test를 하던중 이상한 현상을 발견했습니다.

현재 Postgresql-7.1.2를 사용 하고 있습니다.

조만간에 버전을 올릴 계획인데, 상위 버전에서도 아래와 같이 실행이 될지 궁금합니다.

 

===== 실행문 =========

DROP TRIGGER CHK_TG ON CHECK2;

DROP FUNCTION CHK2_TR();

 

DROP TABLE CHECK2;

DROP TABLE CCK;

 

DROP SEQUENCE cck_cck_no_seq;

DROP SEQUENCE check2_chk_no_seq;

 

 

CREATE TABLE CHECK2(

CHK_NO SERIAL PRIMARY KEY,

CHK_NAME VARCHAR,

CHK_V1 INT NOT NULL DEFAULT 0,

CHK_V2 INT NOT NULL DEFAULT 0);

 

CREATE TABLE CCK(

CCK_NO SERIAL PRIMARY KEY,

CCK_NAME VARCHAR,

CCK_V INT);

 

CREATE FUNCTION CHK2_TR() RETURNS OPAQUE AS '

BEGIN

IF ((SELECT CHK_V1 FROM CHECK2 WHERE CHK_NO=old.CHK_NO)=NEW.CHK_V2) THEN

INSERT INTO CCK(CCK_NAME,CCK_V) VALUES(old.CHK_NAME,new.CHK_V2);

DELETE FROM CHECK2 WHERE CHK_NO=OLD.CHK_NO;

END IF;

return old;

END;

' LANGUAGE 'plpgsql';

 

 

CREATE TRIGGER CHK_TG AFTER UPDATE ON CHECK2

FOR EACH ROW EXECUTE PROCEDURE CHK2_TR();

 

INSERT INTO CHECK2(CHK_NAME,CHK_V1) values('빵',3000);

INSERT INTO CHECK2(CHK_NAME,CHK_V1) values('쿠키',2000);

INSERT INTO CHECK2(CHK_NAME,CHK_V1) values('도너츠',5000);

 

SELECT * FROM CHECK2;

SELECT * FROM CCK;

 

UPDATE CHECK2 SET CHK_V2='3000' WHERE CHK_NO=1;

 

SELECT * FROM CHECK2;

SELECT * FROM CCK;

 

UPDATE CHECK2 SET CHK_V2='4000' WHERE CHK_NO=2;

 

SELECT * FROM CHECK2;

SELECT * FROM CCK;

 

UPDATE CHECK2 SET CHK_V1='4000' WHERE CHK_NO=2;

 

SELECT * FROM CHECK2;

SELECT * FROM CCK;

 

=========== 실행 결과 ============

DROP

DROP

DROP

DROP

DROP

DROP

psql:./new/test2:15: NOTICE: CREATE TABLE will create implicit sequence 'check2_chk_no_seq' for SERIAL column 'check2.chk_no'

psql:./new/test2:15: NOTICE: CREATE TABLE/PRIMARY KEY will create implicit index 'check2_pkey' for table 'check2'

CREATE

psql:./new/test2:20: NOTICE: CREATE TABLE will create implicit sequence 'cck_cck_no_seq' for SERIAL column 'cck.cck_no'

psql:./new/test2:20: NOTICE: CREATE TABLE/PRIMARY KEY will create implicit index 'cck_pkey' for table 'cck'

CREATE

CREATE

CREATE

psql:./new/test2:36: NOTICE: check2_chk_no_seq.nextval: sequence was re-created

INSERT 317426 1

INSERT 317427 1

INSERT 317428 1

chk_no | chk_name | chk_v1 | chk_v2

--------+----------+--------+--------

1 | 빵 | 3000 | 0

2 | 쿠키 | 2000 | 0

3 | 도너츠 | 5000 | 0

(3 rows)

 

cck_no | cck_name | cck_v

--------+----------+-------

(0 rows)

psql:./new/test2:43: NOTICE: cck_cck_no_seq.nextval: sequence was re-created

UPDATE 1

chk_no | chk_name | chk_v1 | chk_v2

--------+----------+--------+--------

2 | 쿠키 | 2000 | 0

3 | 도너츠 | 5000 | 0

(2 rows)

 

cck_no | cck_name | cck_v

--------+----------+-------

1 | 빵 | 3000

(1 row)

 

UPDATE 1

chk_no | chk_name | chk_v1 | chk_v2

--------+----------+--------+--------

3 | 도너츠 | 5000 | 0

2 | 쿠키 | 2000 | 4000

(2 rows)

 

cck_no | cck_name | cck_v

--------+----------+-------

1 | 빵 | 3000

(1 row)

 

UPDATE 1

chk_no | chk_name | chk_v1 | chk_v2

--------+----------+--------+--------

3 | 도너츠 | 5000 | 0

(1 row)

 

cck_no | cck_name | cck_v

--------+----------+-------

1 | 빵 | 3000

2 | 쿠키 | 4000

(2 rows)

 

 

======= 궁금한점 ==========

함수에서 chk_v2값을 업데이트 할때..

기존에 있던 chk_v1값과 비교하여 값이 같으면

check2테이블에서 삭제하고 cck테이블에 인서트 하게 되어 있습니다.

chk_v2값을 업데이트 할때는 이상없이 동작합니다.

(사실 저야 위 처럼 동작하는게 더없이 좋지만..)

 

이상한 점은 chk_v1값을 업데이트할때 old.chk_v1과 new.chk_v2를 비교 하고 같으면 해당 row를 삭제하고 cck테이블에 new.chk_v2를 입력 하게 되어 있으므로 에러 발생 내지는 실행이 되지않아야 하는데..

위의 실행결과는 new.chk_v1과 old.chk_v2와 비교 하고 값이 같으므로 해당 row를 삭제 하고 cck테이블에 chk_v1값을 입력합니다.

 

아직 Trigger나 function에 대해서 잘 알지는 못하지만 DB에서 알아서 비교 해야될 값들을 설정해주는 것인지 궁금합니다.

 

고수님들의 한수 가르침을 기다립니다.

긴글읽어 주셔서 감사합니다. :)

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

plpgsql 함수를 이용한 트리거에서의 old. new 레코드(해당 튜플이 되겠지요.)는 말 그대로 그 레코드 전체입니다.

 

위에서 세번째 update 문인

UPDATE CHECK2 SET CHK_V1='4000' WHERE CHK_NO=2;

이놈에서의 new 레코드 값은

2 | 쿠키 | 4000 | 4000

이렇게 되겠지요.

당연히 old 값은

2 | 쿠키 | 2000 | 4000

되구요.

이때, 초보가 범하기 쉬운 착각은

update 에서 chk_v1 만 지정했으니, chk_v2 에 대해서는 plpgsql에서 null로 처리하겠지라는 것이지요.

이렇게 되면 당연히 오류가 나야할 것이고....

 

이게 아니라, 트리거에서의 old, new 값은 위에서 이야기 해당 레코드 전체입니다.

 

즉, 위에서 보여준 결과는 지극히 당연한 처리 결과입니다.

김상기(ioseph)님이 2002-12-27 21:37에 작성한 댓글입니다.

앗! 그렇군요..

제가 new와 old를 잘못 이해 하고 있었군요..

(저는 입력이 없는 값은 null일꺼라 생각하고 있었습니다. ^^;)

정말 감사합니다. ^^;

이승철님이 2002-12-28 10:16에 작성한 댓글입니다.
[Top]
No.
제목
작성자
작성일
조회
4503상관 부질의.. [5]
이경욱
2002-12-31
1040
4502저기요..처음시작하는데.. [2]
배우장
2002-12-30
902
4501[질문] 데이타 insert 후 디스크 공간이 모잘라 에러 낫을경우 [1]
이근호
2002-12-30
1122
4497Trigger에서 이상한 현상?? [2]
이승철
2002-12-26
1223
4496타임스탬프를 연산할수 있는게 있나요? [1]
잠온다
2002-12-25
1115
44937.3.1 컴파일 하니 NLS 에서 걸리는 군요. [1]
정재익
2002-12-24
932
4492[질문] mysql 질의를 postgresql 질의로 바꾸고 있습니다.
이근호
2002-12-23
932
Valid XHTML 1.0!
All about the DATABASE... Copyleft 1999-2024 DSN, All rights reserved.
작업시간: 0.016초, 이곳 서비스는
	PostgreSQL v16.4로 자료를 관리합니다