SharedIT | 묻고 답하기(AMP)

MSSQL 커서 질문드립니다.

안녕하세요.  회사에서 트리거를 통해서 작업을 하려는데 막히는 부분이 있어 문의드립니다.

AA 테이블에 insert가 일어나면 BB 테이블에 해당 발생 순번과 함께 내용이 저장이 되어야 하는데

무슨 영문인지 순번이 적용이 되지 않습니다.  이유가 뭘까요??


AA 테이블

KEY

내용

ABC

1111

WYZ

22222

ABC

333333

BB 테이블 (원하는 내용)

KEY(PK)

KEY_SEQ(PK)

내용

ABC

1

1111

WYZ

1

22222

ABC

2

333333

 BB 테이블에 KEY와 KEY_SEQ가 기본키로 잡혀있어서 KEY_SEQ 를 가져와야 하는데

AA 테이블에서 INSERT가 하나만 일어날 경우 아무 문제가 없는데 여러건의 INSERT가 동시에 일어나면

KEY_SEQ가 증가하지 않아 에러가 일어납니다.

아래는 AA테이블의 트리거 내용입니다.


Declare @key_seq_ABC int = 0

Declare @key_seq_WYZ int = 0


DECLARE Acur CURSOR FAST_FORWARD LOCAL FOR


SELECT  KEY , 내용  FROM INSERTED


OPEN Acur

FETCH NEXT FROM Acur INTO


@KEY,  @내용


WHILE @@FETCH_STATUS = 0


begin


IF @KEY = 'ABC'

   begin

SET @key_seq_ABC = @key_seq_ABC + 1


insert into BB values (@KEY , @key_seq_ABC , @내용)

   end


IF @KEY = 'WYZ'

   begin

SET @key_seq_WYZ = @key_seq_WYZ + 1


insert into BB values (@KEY , @key_seq_WYZ , @내용)

   end


FETCH NEXT FROM Acur INTO

@KEY,  @내용


end


CLOSE Acur

DEALLOCATE Acur

 

Tags : 태그가 없습니다.

7개의 답변이 있습니다.

그저멍하니
  0 추천 | 약 2년 전

BB테이블의 KEY_SEQ(PK)에서

MAX 값을 가져오시도록 하는게 좋을것 같습니다.


select top 1 구문으로 1개만 추출하셔서

order by KEY_SEQ(PK) desc 역순으로 조회조건을 거시고


가져온 한녀석 + 1을 해주시면 될것 같습니다.


topkslee
  0 추천 | 약 2년 전

KEY_SEQ의 목적이 무엇인지 모르겠지만

단순 순번 나열하기 위한 목적이라 Oracle에 sequence 처럼 

MSSQL에 있는 idnentity 사용해서 1씩 증가시키시면

데이터값만 insert하면 중복없이 KEY_SEQ 자동 증가 됩니다.

참고하세요


topkslee | 약 2년 전

오타네요. identity 입니다

빨간신발
  0 추천 | 약 2년 전

pk를 없애니 정상작동한다면 이전에는 pk가 충돌되었다는 의미겠네요.

본문에 올려주신 소스에는 key_seq의 이전값을 가져오는 구문이 없고

key_seq는 1로만 저장되도록 되어 있습니다.

그래서 pk가 충돌되어 저장되지 않은 듯 하네요.

그리고 저런식으로 pk를 관리하시려면 count보다는 max가 더 잘 어울려요.

count로 하면 1~10까지 중가했다가 5번이 삭제되면 count는 9가 나오고 +1하면 10이 됩니다.

10으로 저장되면 기존에 10이 있어서 충돌이 발생합니다.

고로 max를 사용하시는 것을 추천드려요.

빨간신발
  0 추천 | 약 2년 전

Declare @key_seq int = 1

DECLARE Acur CURSOR FAST_FORWARD LOCAL FOR

SELECT  KEY , 내용  FROM INSERTED

OPEN Acur

FETCH NEXT FROM Acur INTO


@KEY,  @내용


IF @@FETCH_STATUS = 0


begin


select @key_seq  = max(isnull(key_seq, 0)) + 1

   from bb

 where key = @KEY


insert into BB values (@KEY , @key_seq , @내용)

FETCH NEXT FROM Acur INTO

@KEY,  @내용


end


CLOSE Acur

DEALLOCATE Acur


===============


실제 돌려본 것은 아니라서 일부 자잘한 오류가 있을 수 있습니다.


insert이므로 while보다는 if가 나을 듯 합니다. 둘다 없어도 무방합니다.


key값에 따른 @key_seq 변수를 각각 선언할 필요는 없고 하나만 사용해도 됩니다.


단순 +1은 DB에 저장된 최종값을 불러오는 부분이 없으므로 항상 1이 기록됩니다.


그래서 bb테이블에서 key 값에 따라서 key_seq의 최대값을 불러오고 +1을 해주도록 변경했습니다.


저도 예전에 이런식으로 pk1, pk2를 두고 pk1에 따라서 pk2를 개별 증가시키는 것을 구상했었는데


결론은 비효율적입니다. 


매번 bb테이블을 풀스캔하여 max값을 불러와서 계산해주는 프로세스가 필요하고,


그렇게 한들 데이터관리의 이점이 별로 없었습니다.


pk1, pk2을 두고 pk1은 구분자 ex) id 등


pk2은 그냥 정수형으로 increment 걸어주는 것이 편해요.

hgp33 | 약 2년 전

일단 찜찜하지만 원인을 찾았습니다. PK 설정이 잘못되어 있는 듯 했습니다. 그런데도 여전히 의문이 풀리지 않네요 ㅎㅎ;; 분명 MAX 든 COUNT 를 가져와 + 1을 했는데 조회가 안되었던...;;

이상하게 PK를 삭제를 하니 정상적으로 SEQ도 증가를 하고 중복이 없어졌네요 ㄷㄷ;;;

이것 참 머리가 아프네요 원인을 알아야 방지를 할터인데 .. 감사합니다~!!

wansoo | 약 2년 전

PK를 제거했다는게 AA Table에서 PK를 제거 했다는 말씀이신가요?

PK에는 Unique 속성이 포함되어 있기 때문에 'ABC'가 이미 들어가 있는 상태에서 'ABC'가 다시 입력되게 되면 unique 속성에 위배되기 때문에 입력 자체가 안되게 되겠고요.

BB table에는 key와 key_seq 합해서 Primary key이기 때문에...

key 값과 key_seq 값이 함께 insert된다면 문제가 없을것 같아 보이고...

wansoo
  0 추천 | 약 2년 전

에러가 일어난다면 에러 메시지 내용이 무엇인지를 먼저 확인해서

문제 원인을 찾아야 하지 않을까 싶어 보이네요.


MS SQL을 잘 다루지 않다 보니... 원하는 답변을 적기는 어려울것 같고요.


DB라는 건 가급적이면 데이터가 중복되지 않게 설계하는게 좋을 것 같은데...

AA 테이블에 순번이 생성되게 하는 식으로 관리하면 될 것 같은데...

왜?? BB라는 테이블을 만들어서 데이터가 2중으로 저장되게 설계하려는지 궁금하네요.

BB가 꼭 필요하다면 테이블로 만드는것 보다는 뷰로 만드는게 낫지 않을까 싶어 보이고...


BB 테이블에 저렇게 순번을 만들려는 이유가 Primary key가 unique하게 하기 위해서 인가요?

그냥 순번 필드를 자동 발생되게 만들어 버리는게 더 간단하지 않을까 하는 생각도 들어 보이고요.


그리고...

AA 테이블 KEY 필드에는 'ABC'와 'WYZ'만 입력되나요??

입력되는 데이터 만큼의 변수를 만들어서 순번을 만들어 주려는 걸까요?? ^^;;


차라리

key_seq_ABC, key_SEQ_WYZ 와 같이 여러개의 변수를 선언해 주고 사용할 게 아니라

key_seq라는 변수만 선언해 주고서


SET @key_seq_ABC = @key_seq_ABC + 1

부분을

set @key_seq = ( select count(key) from AA where key = @KEY )

와 같은 형식으로 해 주면 되지 않을까 싶어 보이고요.

hgp33 | 약 2년 전

전체 내용을 올리기에는 너무 내용이 길어 핵심 질문만 올렸습니다.

KEY 값은 고정값입니다~ 알려주신 내용처럼 조회를 해봐도 count 값을 가져오질 못합니다.

따로 조회하면 키값을 가져오고요 도통 이해를 못하겠습니다. ㅠㅠ

wansoo | 약 2년 전

혹시 lock과 관련되지는 않을지도 의심해 볼 필요가 있을 것 같아 보이네요.

AA table insert하면서 lock 걸어두고서 lock 해제되지 않아서 접근을 하지 못해서 오류가 난다거나...

명동쓰레빠
  0 추천 | 약 2년 전

스크립트를 올리시면 해결이 빠를것 같네요

텍스트로 보니 잘 구분이 안되네요.

제가 어필 보기에는  @key_seq_ABC 에 조건이 맞으면 1을 더해서 처리 하는대

선언에서

Declare @key_seq_ABC int = 0

Declare @key_seq_WYZ int = 0

매번 0으로 처리하고 1을 더하는것 같네요 처음 하나는 1이 더해 지는대 그 다음 데이터도  0으로 만들고 또 1을 더하는것 같습니다.


hgp33 | 약 2년 전

저도 이부분이 의심되어 매번 insert 진행전에 현재 값을 조회하는 구문도 추가를 해보았습니다.

그런데도 조회를 하지못하더라고요;; 따로 조회를 하면 조회가 되고요;; 유독 트리거에서만 작동

을 안하네요 ㅎㅎ;; 

topkslee
  0 추천 | 약 2년 전

BB 테이블의 PK가 어떻게 설정되어 있는지요?

KEY, KEY_SEQ 개별로 PK 잡혀 있는지?

아니면 KEY+KEY_SEQ로 PK 잡혀 있는지 체크 해보세요.

PK가 개별로 잡혀 있으면 PK 위반으로 에러 날것 같네요

hgp33 | 약 2년 전

답변을 보고 PK를 삭제하니 정상적으로 insert가 됩니다.

어째서 PK를 그리 잡았는지 테이블을 구성하신 분하고 다시 협의가 필요할 것 같습니다.

감사합니다~!!

topkslee | 약 2년 전

네 구문상으로는 일반적인 내용이라 이상이 없어 보였습니다.

해결되셨다니 다행입니다.

topkslee | 약 2년 전

KEY+KEY_SEQ 가 중복이 없다면 복합 PK 생성하셔서 구성하시면 될것 같습니다.