퇴근5분전



DECLARE
    DT1 DATE := TO_DATE( '201001' , 'YYYYMM');
    DT2 DATE := TO_DATE( '201002' , 'YYYYMM');
    CNT INT := MONTHS_BETWEEN( DT2, DT1) + 1;
    IDX INT := 0;
    DT  DATE;
BEGIN

    WHILE IDX <= CNT LOOP
   
      DBMS_OUTPUT.PUT_LINE( IDX );
  
      DT := ADD_MONTHS( DT1, IDX );
      
      INSERT INTO 임시테이블
      VALUES ( DT );
      
      IDX := IDX + 1;
     
      EXIT WHEN IDX > CNT;

    END LOOP;

    SELECT YMD FROM 임시테이블; COMMIT;              -- INTO를 요구한다.

END;

    SELECT YMD FROM 임시테이블;  COMMIT;              -- 정상적인 위치

 

 위 쿼리는 작업 중 MS-SQL에 익숙해진 생각에서 시작했다. 

 항목별 기간 데이타를 만들기 위해 사용 될 기간테이블로 항목별 테이블과 크로스 조인을 통해 데이타를 생성하려는 목적으로 임시테이블을 토드에서 테스트 하기 위해 만들어진 스크립트 임.

 팀장님께서 말씀하시는 데로는 INTO요구하는 곳에서 나오는것은 맞다고 한다. 어딘가 담아야 된다고??  하심.

오라클이 1개의 쿼리만을 허용한다고 얘기는 얼핏 들었지만... 위 같은 상황일거란 생각은...

정상적인 위치로 옮겼을경우 F5를 통해 결과를 얻을수 있지만.  F9를 통해서는 여전히 문법 오류를 반환한다.

아 특이해...

이번 플젝 성패는 오라클을 얼마나 빨리 습득하느냐에 따라 결판날듯 한뎁... 오라클 검색하면 왜케 어렵게 보이는지...

MS-SQL이 쉽다는걸 다시 느꼈다.

 


DROP TABLE 임시테이블명 CASCADE CONSTRAINTS;

CREATE GLOBAL TEMPORARY TABLE 임시테이블명
(
  YMD  DATE
)
ON COMMIT DELETE ROWS   -- Commit 시 임시 데이타는 모두 사라짐.

NOCACHE;

임시테이블 만드는 스트립트임.


옵션이 하나 더 있는데 오라클 임시테이블 치면 블로그 글이 많이 뜸.






프로시져 실행시... F5나 F9로 제대로 실행이 안되서 토드에서 번개아이콘 클릭해서 파라미터 설정후에 콜했었으나...


EXEC 프로시져명( 1 ,:VAR ) [ 음 이건 다시 해보니 안됨? 그때 뭔가에 씌였었나... ]

프로시져명( 1 ,:VAR ) [ 이건 되는걸 확인했음 ]


쿼리문 선택후 F5나 F9 또는 Ctrl + Enter를 클릭시 파라미터를 설정하는 다일로그 하나가 뜬다.

Var는 Cursor 타입으로 지정하면 된다.

: 김영삼씨 덕분에 알게 되었음... 감솨!

Ms-SQL의 sys.Objects 같은 내부 뷰 등으로 간단한 사용툴들을 만들었는데

오라클은 아래 링크에서 확인 가능함.


http://blog.naver.com/kmymk?Redirect=Log&logNo=110082928906


간만에 쿼리 쓸라니 기억이 안나서 어렵군...

갑자기 피벗 쓸일이 있었는데... 가물 가물한 기억땜시롱...

간단한 예제로 써놓는답.

SELECT y, sum( case c when 'A' then i else 0 end ) AS AColumn ,sum( case A.c when 'B' then i else 0 end ) AS BColumn
FROM
(
 SELECT '200812' AS Y , 'A' AS C, '1' AS I
 UNION
 SELECT '200812', 'B', '2'
 )a
group by A.y


결과
Y           AColumn  BColumn
200812    1             2



Sum이 기억이 안나서 무진장 헤맸뉑...

CTE는 왜이리 어렵누..


추가 ~~~  : 반대로 할경우!!!


SELECT A.A, CASE B.[K]  WHEN 1 THEN A.[1]
      WHEN 2 THEN A.[2]
      WHEN 3 THEN A.[3]
      WHEN 4 THEN A.[4]
      WHEN 5 THEN A.[5] END AS M
FROM
(
 SELECT 'A' [A], 1 [1], 2 [2],3 [3],4 [4],5 [5]
)A
,
(
SELECT 1 K
UNION ALL
SELECT 2 K
UNION ALL
SELECT 3 K
UNION ALL
SELECT 4 K
UNION ALL
SELECT 5 K
)B




 

 오늘 한 삽질을 기록하다.

테이블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 'ㄴ' 하게 되면
ㄱ 으로 시작하는 첫글자를 대상으로 조회 해왔다
ㄴ이 오지는 않았다. ㄴ대신 ㄷ 을 넣게 되면 ㄱ , ㄴ 으로 시작하는 첫글자들을 결과집합으로
쿼리해오더라