이틀을 고생하여 알아낸(알아낸건 아니구 또 삽질에 의한 방법 or 노하우 : 더 좋은 방법이 있음 알려주세요)
방법을 이곳에 기록합니다.

일단 이슈는...
대략 이렇습니다.

기존에 레코드에 새로운 데이터를 insert 한다.
그리고 그 insert 한 값을 알아낸다...

머 그리 어려운것도 아니네 하겠지만

이번에 제가 해야만 하는 프로그래밍에는 여러가지 제악조건이 있었습니다.
1. 특정 컬럼이 부분 유니크 해야한다.
이말이 먼말이냐하면 예를 들어 file_no 라는 컬럼이 1 부터 6500 까지 중복된 값이 없어야합니다.
insert 할때 file_no 값이 1부터 6500 까지 자동증가해야합니다.
중복된 값이 없어야하고 만일 6500 까지 되었으면 다시 1부터 시작해야합니다.
그러기 위해서는 insert 전에 select 를 하여서 마지막 값을 알아야합니다.
머 그리 어렵지 않게 어떻게 해야하는지 그림이 그려지는 분들도 있을것입니다.

select top 1 file_no from ex_TBL order by idx desc
(idx는 자연증가하는 컬럼)

file_no = file_no +1
if file_no > 6500 then
file_no = 1
end if

insert ex_TBL(file_no) values(file_no)

이런식으로요..
다음 조건을 보시죠...ㅡㅡ;

2.여러사람이 동시에 접속하는경우도 대비해야한다.
한거번에 여러사람이 몰리면
select 문이 실행되서 insert 문이 실행되기전에
또다른 select 문이 실행되어버려서
같은 값을 가질수있게됩니다.
그럼 중복된 값이 inser될수 있겠죠?

lock 를 생각하시는 분이 있으실것입니다.
오케이 일단 넘어가겠습니다.

3.입력된 file_no 가 과연 무엇이 들어갔는지 알아야된다.
사실 file_no는 화일명을 정하는 값이라서 그값을 가지고
서버에 화일을 저장해야합니다.
여러분이 그래야되는것이 아니라 제가 해야할것이 그랬다구요..ㅜ.ㅜ;

머 이것만 때서 생각해보면
다시 select 문을 써서 알아내면 되지 않느냐고 말하시는 분들이 있을겁니다.
이것도 일단 오케이....

자자자 이제 위에 조건들을 모아보면...머리가 아파오기 시작할겁니다.
물론 아니신 고수분들도 있을겁니다...ㅜ.ㅜ;

그럼 제가 이것을 어떻게 처리했는지 기록하겠습니다.
일단 select 문 2개와 insert문 1개가 동시에 처리되어야합니다.

당근 trans 를 생각하시겠죠?
db.begintrans
.
.
.
db.committrans

하지만 이것만으론 잘안되더군요.

어떻게 테스트를 했냐면요.
100번정도 for 문으로 막 돌린 asp 페이지를 여러브라우저에 띄워 한거번에 리플래쉬를 해봤습니다.

쿼리를 던지고 받는 시간을 줄이기위하여 sp 를 사용하였습니다.
중복되는 비율은 적어졌지만 여전히 중복데이타가 나오는 현상이 있었습니다.

이번에는 select 문 1개와 insert 문 1개 그리고 비교구분 1개를 하나의 쿼리로 만들었습니다.
(위에 1.번을 참조)

insert into ex_TBL(file_no,id) select top 1  k =  (case when isnull(file_no,0) + 1 > 6500 then 1
else isnull(file_no,0) + 1 end)  ,@id from ex_TBL with (serializable) ORDER by idx desc

위에 @id 는 유저아이디

그리고 with (serializable) 문을 통하여 lock 을 걸었습니다.

그리곤
select top 1 file_no from ex_TBL where id=@id order by idx desc
을 선언하여 유저의 가장최근에 저장된 file_no를 리턴하였습니다.

끝입니다...
저도 까먹을까봐 자세하게 적을려고 했는데
적어보니 너무 단순하고 설명이 약한것 같습니다...ㅡㅡ;

Posted by 빨강토끼
,