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 6306 게시물 읽기
No. 6306
[질문]중복됨 없이 숫자를 입력되게 하려면.
작성자
가우나라(familyj)
작성일
2005-09-06 02:34
조회수
2,293

A 라는 테이블에는

nOutputNum serial not null priamry key,

nReceiptNum integer not null,

chEtc varchar(255)

라는 구조로 되어 있습니다.

 

그런데, nReceiptNum 은 여태까지 입력된 max(nReceiptNum) + 1 의 형태로 넣고자 합니다.

단, serial 의 형식은 안됩니다.

 

문제는 여러명의 접속자가 A 라는 테이블에 접근하는데요.

간혹 똑같은 nReceiptNum 이 입력되는 경우가 있습니다.아마 동시에 A 라는 테이블에 접근한것 같습니다.

 

위와 같이 여러명이 동시에 접속하더라도, nReceiptNum 에는 서로다르게 숫자를 입력받게끔 하는 방법이 있을까요?

 

 

 

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

시퀜스가 좋은방법이지만 그게안된다면

UPDATE A set nReceiptNum =

(SELECT (max(nReceiptNum)+1) FROM A)

 

%) create unique index i_A on A(nReceiptNum);

요게 있슴 좋겟네요

 

 

가우님이 2005-09-06 07:47에 작성한 댓글입니다. Edit

가우님의 방법이 유일한 값을 얻는 방법인지 확신이 안서네요. 동시에 저 명령어가 여러번 실행이 되면 같은 nReceiptNum이 나오지 않을까요?

 

저는 그래서 이렇게 사용합니다.

 

begin tran;

lock table a in share;

select nReceiptNum from a order by nReceiptNum desc limit 1; // 이 값을 변수에 넣습니다.

insert into a values(???, 변수값+1); // 변수에 넣은 값을 사용합니다.

commit tran;

 

하지만 이 방법은 트렌젝션이 끝나기 전에 table에 대한 모든 기록을 차단하기 때문에 다량의 update가 발생하는 상황에는 성능에 나쁜 영향을 줄 수 있습니다. 유일한 값을 얻으려면 어쩔 수 없을 듯 합니다.

 

8.1 부터는 max()도 인덱스를 사용하지만 아직은 index를 사용하지 않기 때문에 작동이 느린 것으로 알고 있습니다. 그래서 order by와 limit를 사용하는 것이 더 빠릅니다.

 

박성철(gyumee)님이 2005-09-06 10:06에 작성한 댓글입니다.
이 댓글은 2005-09-06 10:10에 마지막으로 수정되었습니다.

우와..

전 GUID또는

now()의 결과값(1000등분 더해서)을 포멧으로 해서

중복이 없는 값을 만들어 내는데..^^;

 

방법은 가지가지로 존재한느군요 +_ +

굳굳 +_+)b

이현순(foolbabo)님이 2005-09-06 10:40에 작성한 댓글입니다.
이 댓글은 2005-09-06 10:40에 마지막으로 수정되었습니다.

저도 이런 경우는 주로 시퀜스를 쓰지만 상황에 따라서는 테이블을 2개 사용합니다.

 

A 테이블 구조는 그대로 두고 B테이블에는 max값만 저장

사용시엔 B의 값을 읽고 +1 해둔 다음

그값을 그대로 A 테이블의 nOutputNum 값으로 사용...

 

INSERT보다 UPDATE가 주로 많으며 DELETE를 절대로 하지 않는 테이블일 때 활용하면 나름대로 도움이 됩니다.

 

물론 B에 동시에 다수의 유저가 접근하면 같은 값이 나올수도 있긴 하군요...

그래도 priamry key로 설정해놔서 에러한번 나오고 튕기니까...

어플리케이션에서 이런 에러가 리턴될 때는 인터벌두고 다시 재입력하도록 설정하면 되긴하죠.

 

김영호(icepage)님이 2005-09-06 14:04에 작성한 댓글입니다.
이 댓글은 2005-09-06 14:10에 마지막으로 수정되었습니다.

저도 사실은 시퀀스 대신에 다른 방법을 써야 할 때에는 김영호님의 방법을 사용합니다.

 

하지만 가우나라님의 요청이 max()+1로 해결해 달라는 것 같아서 저렇게 제안을 해드렸습니다.

 

그리고 김영호님의 방법에서 동시에 중복해서 값이 나오지 않게 하려면 select ... for update 구문을 사용하면 됩니다.

 

select ... for update 구문을 사용하면 select된 해당 row들에 row level lock이 걸려서 다른 select... for update 구문들이 대기 상태가 됩니다. pgsql이 mysql과 다른게 이런 것 아니겠어요? ㅋㅋㅋ row level lock은 informix도 안되던 것이죠. 나중에는 됐었나?

박성철(gyumee)님이 2005-09-06 16:15에 작성한 댓글입니다.

도큐먼트에

SELECT FOR UPDATE of these rows will be blocked until the current transaction ends.

이 항목을 보니 성철님 말씀이 맞네요.

 

써브쿼리에 for update를 쓸수있다면 좋은데...

이건 광범위한 lock을 유발시켜 허용시키지 않는지,락이걸린 같은 row에 수정을 해야하는것자체가 논리오류라서 그런건지 허용이 안되네요

 

가우님이 2005-09-06 16:23에 작성한 댓글입니다. Edit
[Top]
No.
제목
작성자
작성일
조회
6309윈도우용 설치파일을 [2]
초보
2005-09-09
1822
6308외래키를 한 필드에 여러개 물려줬을때... [1]
가시고기
2005-09-07
1950
6307라이브러리 호환 방법 문의? [5]
ssik425
2005-09-06
1675
6306[질문]중복됨 없이 숫자를 입력되게 하려면. [6]
가우나라
2005-09-06
2293
6305다중 IP를 사용하는 시스템에서 pgsql연결.. [4]
이현순
2005-09-05
2384
6304rowacount와 동일한 명령어 아시는분 좀 가르쳐 주세요... [5]
이정호
2005-09-03
2198
6303initdb 질문입니다. [1]
김종섭
2005-09-02
1837
Valid XHTML 1.0!
All about the DATABASE... Copyleft 1999-2024 DSN, All rights reserved.
작업시간: 0.018초, 이곳 서비스는
	PostgreSQL v16.2로 자료를 관리합니다