http://redrebel.egloos.com/1717186 <-예전에 올렸던 방법
고수님이 도와주셔서 제가 먼저 등록했던 방법을 고쳤습니다.
정말 깔끔하게 떨어지더군요^^;
구현하려고하는 기능과 해야될 조건들은 예전의 글을 참조하세염.
방법은 테이블하나를 더 추가하여 하나의 레코드에 하나의 컬럼만을 생성한다.
CREATE TABLE [dbo].[ex_no_TBL] (
[idx] [int]
GO
이테이블에 sp가 접근을 하는데 sp는 테이블의 레코드를 1씩증가시키며 6500 이 넘으면 다시 1로 바뀌는 역활을한다.
CREATE PROC [dbo].[get_fileno]
--로컬변수 선언
@TextMaxNum int output
as
set nocount on
begin tran
update ex_no_TBL set idx = (case when idx+1 > 6500 then 1 else idx+1 end)
select @TextMaxNum=idx from flashmall_user.dbo.ex04
commit tran
RETURN(@TextMaxNum)
GO
asp 페이지에서 sp를 호출한다음에 @TextMaxNum 를 리턴받는다.
Set cmd = server.CreateObject("ADODB.command")
With cmd
.ActiveConnection = db 'open된 db
.CommandType = 4 'adCmdStoredProc 입니다. sp 접근시... 1는 text입니다.
.CommandText = "get_fileno"
.Parameters.Refresh
.Execute
End With
dim file_no
file_no = cmd.Parameters("@TextMaxNum").Value
sqlString = "insert into ex_TBL(c1,id) values("&file_no&",'"&id&"')"
db.execute sqlString
id 는 유저아이디입니다.
고수님이 도와주셔서 제가 먼저 등록했던 방법을 고쳤습니다.
정말 깔끔하게 떨어지더군요^^;
구현하려고하는 기능과 해야될 조건들은 예전의 글을 참조하세염.
방법은 테이블하나를 더 추가하여 하나의 레코드에 하나의 컬럼만을 생성한다.
CREATE TABLE [dbo].[ex_no_TBL] (
[idx] [int]
GO
이테이블에 sp가 접근을 하는데 sp는 테이블의 레코드를 1씩증가시키며 6500 이 넘으면 다시 1로 바뀌는 역활을한다.
CREATE PROC [dbo].[get_fileno]
--로컬변수 선언
@TextMaxNum int output
as
set nocount on
begin tran
update ex_no_TBL set idx = (case when idx+1 > 6500 then 1 else idx+1 end)
select @TextMaxNum=idx from flashmall_user.dbo.ex04
commit tran
RETURN(@TextMaxNum)
GO
asp 페이지에서 sp를 호출한다음에 @TextMaxNum 를 리턴받는다.
Set cmd = server.CreateObject("ADODB.command")
With cmd
.ActiveConnection = db 'open된 db
.CommandType = 4 'adCmdStoredProc 입니다. sp 접근시... 1는 text입니다.
.CommandText = "get_fileno"
.Parameters.Refresh
.Execute
End With
dim file_no
file_no = cmd.Parameters("@TextMaxNum").Value
sqlString = "insert into ex_TBL(c1,id) values("&file_no&",'"&id&"')"
db.execute sqlString
id 는 유저아이디입니다.
이틀을 고생하여 알아낸(알아낸건 아니구 또 삽질에 의한 방법 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를 리턴하였습니다.
끝입니다...
저도 까먹을까봐 자세하게 적을려고 했는데
적어보니 너무 단순하고 설명이 약한것 같습니다...ㅡㅡ;
방법을 이곳에 기록합니다.
일단 이슈는...
대략 이렇습니다.
기존에 레코드에 새로운 데이터를 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를 리턴하였습니다.
끝입니다...
저도 까먹을까봐 자세하게 적을려고 했는데
적어보니 너무 단순하고 설명이 약한것 같습니다...ㅡㅡ;