퇴근5분전

 오늘 한 삽질을 기록하다.

테이블1
(              
         BankNum,  -- PK
         Sno           -- FK  Referance [테이블1].[Sno]
 )

테이블2
(
       Sno             -- PK
)

두개의 테이블이 있다.
 
[테이블1]에는 5000개의 데이타가 이미 들어가 존재하고
[테이블2]는 다른 정보로 가득 차있다.
두테이블은 Sno로 연계관계가 성립한다.

 이건 기본적으로 [테이블1]을 바탕으로 해서 넣기 때문에
[테이블2]에서는 Sno를 얻어다가 업데이트 하게 되는 형태로 이때 Sno갯수는 가변적이다.

여기서 나의 왕고집이 또한번 빛을 발휘한다.
"원샷 쿼리로 어찌 어찌 해보자..."
우선 삽질과 함께 헤매이게된 조건을 기록해보면.
난 커서를 모른다. ( 공부만 했지 적용은 안해봐서.. 응용에 대해 무지하다. )
그리고 테스트중인 Sql서버가 Ms-Sql 2000 이었다. ( 줸장! )
-> 2000이란 존재는 내가 다뤘던 2005보다는 좀더 쿼리가 복잡해진다. 쑈를 더한다는거...
-> 내가 기억하는 쿼리로 아무리 풀려해도 오류가 떠서 확인해보니 2000 이었더라..
-> 난 2005인줄 알고 있었을 뿐이고~

테이블1에 데이타를 넣어야 되는데 Sno null이고 테이블2는 테이블1과 연계될게 없었는데
난 오늘 이걸 종일 매치 시키려고 애썼따.
결과는 물론 나왔지만 성능상 몹쓸쿼리가 되었음에 고집을 접었다.

잘못된 판단으로의 접근 :
 1. 내가 생각했던 방법은 테이블1 - 테이블2 에서 서로 매치되는게
  없으므로 테이블2에서 선택된 Sno 값들에 대해 임시 테이블을 만들면서 번호를 붙이고
 2. 테이블1도 임시테이블로 만들면서 행번호를 만들어서
 3. 서로 두 임시 테이블을 조인 후
 4. 그 테이블로 테이블1에 업데이트를 시도한다!

 첨엔 그럴싸 했고 업데이트문을 하나로 할수 있어보여서 왠지... 더욱더 해보자라는 강한 의지가...
단, 임시테이블이 걸리는데 ...

<< 삽질 쿼리 >>
SELECT  SNO  
INTO #TABLE1 
FROM [STUDENT](NOLOCK)
WHERE SNO IN ('2007A131       ','20052109       '); 

SELECT (SELECT COUNT(*) FROM #TABLE1 AS B WHERE B.SNO <= A.SNO) AS NUM, A.SNO  
INTO #TABLE3 
FROM #TABLE1 AS A;

SELECT  BANKNUM, BANKCODE 
INTO #TABLE2
FROM BANKNO AS A(NOLOCK)
WHERE   SNO IS NULL;
 
SELECT  ( SELECT  COUNT( * ) FROM #TABLE2 AS B WHERE B.BANKNUM <= A.BANKNUM ) AS NUM, A.BANKNUM, A.BANKCODE 
INTO #TABLE4
FROM #TABLE2 AS A;

   
UPDATE [BANKNO] SET 
[BANKNO].[SNO] = [SOURCE].[SNO], 
[BANKNO].[SDATE] = CONVERT(CHAR(10), GETDATE(), 120), 
[BANKNO].[FDATE] = CONVERT(CHAR(10), GETDATE(), 120) 
FROM 
(
 SELECT TB1.NUM, TB1.BANKNUM, TB2.SNO, TB1.BANKCODE    
 FROM #TABLE3 AS TB1   
 INNER JOIN #TABLE4 AS TB2 ON TB1.NUM = TB2.NUM 
)AS [SOURCE] 
WHERE   [BANKNO].BANKNUM = [SOURCE].BANKNUM 
AND  [BANKNO].BANKCODE = [SOURCE].BANKCODE;   

DROP TABLE #TABLE1;  DROP TABLE #TABLE2;  DROP TABLE #TABLE3;



일반적으로 사용하는 1개 행씩업데이트 하는 구문 말고, 어떤 대상을 가지고 업데이트 하는 방법을 찾아
Update문을 찾아서 확인.

Form절 이 있었고 이를 적용해보았다. ( 임시테이블을 잘못 써서 삽질한 얘기는 패쑤 ~ )

대략 기록하자면 아래 와 같다.
------------------------------------------------------
Update 테이블  Set
컬럼 = 값
From 대상
where 테이블.조건 컬럼  = 대상.조건컬럼
------------------------------------------------------

여기서 Where문에 걸어줄 조건 땜시롱 위에서 얘기한 로직으로 만들었는데...

동작은 되는데 임시테이블 5000개에 번호를 붙이다 보니 이게 성능상 문제가 되어버렸다.

너무 길어져서 결론을 쓴다.

1개행씩 처리하고 쿼리는 더욱 간단해졌다.

순서 :
    1. 선택된 Sno 목록화 하고
    2. 루프를 돌면서 1개행씩 업데이트 하되 대상은 Sno가 빈 BankNum로 한다.

구문은
UPDATE BANKNO SET
SNO = '2007A131'
FROM ( SELECT TOP 1 BANKNUM, BANKCODE FROM BANKNO(NOLOCK) WHERE SNO IS NULL )AS [SOURCE]
WHERE BANKNO.BANKNUM = SOURCE.BANKNUM AND BANKNO.BANKCODE = SOURCE.BANKCODE
 

참 짧게 되었찌! 췌.. 이걸 6시간동안 고민하고 생각하고 ..;;
요새 슬럼프라 일도 안되고 재미도 없고 ...


다시 내린 결론은 어떤 문제에 대한 해결방법은 " 쉽게 생각하자."  였다.
내가 굳이 어렵게 생각할 필요는 없으니 ~ !!
아는 한도내에서 쉽게 쉽게...












declare  @hangle_jaeum varchar(100)
declare  @startchar char(2)
declare  @endchar char(2)

set  @hangle_jaeum = 'ㄱㄴㄷㄹㅁㅂㅅㅇㅈㅊㅋㅌㅍㅎ'
set  @startchar = @WORD
set  @endchar  = SUBSTRING( @hangle_jaeum, charindex( @startchar, @hangle_jaeum, 0 )+1, 1 )

print ( SUBSTRING( @hangle_jaeum, charindex( @startchar, @hangle_jaeum, 0 )+1,1 )  )
print ('s:'+ @startchar  + ' e:' +  @endchar)

SELECT *
FROM [테이블]
WHERE [NAME] BETWEEN @startchar AND @endchar

SQL 문을 도와주다가 이름을 ㄱ~ ㅎ으로 찾는 주소록 관련해서
쿼리를 살짝 도와주고 CASE문으로 조합하여 해당 쿼리를 완성해서 준적이 있었으나.
위 BETWEEN으로 된다고 하여 신기해서 블로그에 적어둠.
SQL에서의 어떤 속성값이 지원하는지? 아님 기본으로 지원이 되는것인지는 모르겠으나.

BETWEEN 'ㄱ' AND 'ㄴ' 하게 되면
ㄱ 으로 시작하는 첫글자를 대상으로 조회 해왔다
ㄴ이 오지는 않았다. ㄴ대신 ㄷ 을 넣게 되면 ㄱ , ㄴ 으로 시작하는 첫글자들을 결과집합으로
쿼리해오더라