퇴근5분전

에러 내용 : 

        ssms를 켜고 솔루션 창이나 출력, 속성창등을 드래그 해서 창을 프로그램에서 꺼낸 후 다시 드래그로

     원하는 위치로 넣을때 프로그램이 종료되는 현상.

 

 

해결방법 : 

    docs.microsoft.com/en-us/answers/questions/263738/ssms-188-crashes-when-re-docking-tabs.html

 

SSMS 18.8 crashes when re-docking tabs - Microsoft Q&A

 

docs.microsoft.com

   VinnieAmir-0621   <---- 이사람 답변

 

 구글번역 : 

모든 SSMS 창을 닫고 SQL Mgt Studio EXE 파일을 찾으십시오.

C:\Program Files(x86)\Microsoft SQL Server Management Studio 18\Common7\IDE 찾을 수 없는 경우

SSMS를 여는 데 사용하는 바로 가기를 마우스 오른쪽 단추로 클릭하고 속성> 파일 위치 열기로 이동합니다.

이 파일을 찾으면 "Ssms.exe.config"라는 파일도 찾아서 관리자 모드에서 메모장을 열고이 파일을 편집합니다.

그런 다음 라는 xml 태그를 찾아야하며 다음을 정확히 APPEND (대체 아님)해야합니다.

;Switch.System.Windows.Interop.MouseInput.OptOutOfMoveToChromedWindowFix=true;Switch.System.Windows.Interop.MouseInput.DoNotOptOutOfMoveToChromedWindowFix=true

 

ssms.exe.config 중에서 수정한 부분

 

그리고 그게 다입니다. 이제이 불쾌한 충돌을 피할 수 있습니다.

https://support.microsoft.com/en-us/topic/february-9-2021-kb4601060-cumulative-update-for-net-framework-3-5-and-4-7-2-for-windows-10-version-1809-and-windows-server-version-2019-b240d07e-639f-d708-98c9-0cbe443176aa

 

 

ps : 

    새 프로젝트를 시작하면서 기존 노트북이 망가져서 새 노트북에 환경설정을 마쳤었다. 

   크리스탈 리포트 관련 이슈가 있어서 해결하는 과정에서 ssms를 실행하고 프로시저를 확인하려고 

  내가 만들어 넣은 오브젝트 탐색기를 가동시켜 프로시저를 찾았는데...

  이게 설정 후 처음 열리는 것이라 팝업형태로 떠있길래 드래그 해서 프로그램안으로 밀어넣었는데... 

  강제종료??? 

 

  여러번 해봤지만 역시나 에러로 종료되어 내 개발pc에서 확장프로그램 소스를 이용하여 ssms를 열고 동일한 에러가 발생하였다. ssms버젼확인 후 18.5에서 해결되었다는 글을 보고 최신버젼 18.8을 설치하였으나 동일한 증상이 일어났다.

 

  혹시나 하여 14, 16, 17버젼 모두 실행해서 확인해본결과 14빼고 모두 동일하게 강제종료 되었다.

 잘 되던게 왜이러나 하고... 고민하던 중에... 내가 만든 것만 그런가? 라는 생각에...

 ssms에 원래 있던 창인 "출력" 창을 열어서 드래그해서 붙여보니 ... 동일하게 강제종료 현상이 발생하였다. 

다행이 내 프로그램문제는 아니구나 하고 검색... 검색... ....

 

 찾았다. 영어가 안되는게 참 서글픈... 크롬에서 번역기능이 없었으면... 찾았을까 싶다.

 머리가 나빠서 쉽지 않은 삶이야...

 

 

 

 

sqler 질문글..

http://www.sqler.com/942478#1

 

아래처럼 풀이해봤음.

 

/*
col1 | col2

 1       10

 2       20

 3       30

 4       40

*/


;with tb
as
(
 select 1 as col1, 10 as col2
 union
 select 2 as col1, 20 as col2
 union
 select 3 as col1, 30 as col2
 union
 select 4 as col1, 40 as col2
)

select case when col = 1 then tmp1.col1 else tmp2.col11 end as col1,
   case when col = 1 then tmp1.col2 else tmp2.col22 end as col2
from ( values( 1),( 2 ) ) as tab ( col )
left join
(
 select 1 as k, col1, col2
 from tb
) as tmp1
on   tab.col = tmp1.k
left join
(
 select 2 as k, count( col1 ) as col11, sum( col2 ) as col22
    from tb
) as tmp2
on tab.col = tmp2.k

 

 

 

 

sqler에 질문글..

http://www.sqler.com/bSQLQA/862019

 

심심해서....  

 

 

;with tmp
as
(
select *
from
(
    values 
        (1,         '2008-01-02 00:00:00.000' ),
        (2,          NULL),
        (3,          NULL),
        (4,          '2008-01-03 00:00:00.000'),
        (5,          NULL),
        (6,          NULL),
        (7,          NULL),
        (8,          NULL),
        (9,          '2008-01-04 00:00:00.000'),
        (10,         NULL),
        (11,         NULL)
) as tb (a, b )
)

select a, isnull( b , ( select max( b ) from tmp where a < bs.a )) as bb
from tmp as bs

피벗으로 하는 건데...

문제 차제가 조금 데이타가 부족해보였다.

그림에 보이는데로 나오는 걸 일부 수정해서 풀었지만...

동적으로 늘어나는 데이타 컬럼에 대해서 처리를 위해 동적쿼리를 만들어야 되는데...

과연? 얼마나 사이즈가 늘어날지는 실 데이타로 처리 해봐야 하니 .. 모르겠고,  

 

문제 : http://www.sqler.com/828698#1

 

## 첫풀이 : 공백으로 처리 했지만 char(10)으로 바꾸면 enter값을 넣어서 뿌리는 건 비슷하게 나온다.


;with tb
as
(
    SELECT ITEM_CD, SPEC, SO_DT + ' ' + DLVY_DT + ' '+  SOLD_TO_PARTY_NM as HD, SO_QTY
    FROM (
        VALUES
            ( '41-P006-IVM', 'GAP-6 IV', '2016-05-10', '2016-05-13', 'TMEH-J', 2400 ),
            ( '41-P006-IVM', 'GAP-6 IV', '2016-05-12', '2016-05-20', 'TMEH-J', 4800 ),
            ( '41-P006-IVM', 'GAP-6 IV', '2016-05-17', '2016-05-20', 'TMEH-J', 10800 ),
            ( '41-P006-IVM', 'GAP-6 IV', '2016-05-13', '2016-05-20', 'AXIS', 2400 )

    ) AS TB ( ITEM_CD, SPEC, SO_DT, DLVY_DT, SOLD_TO_PARTY_NM, SO_QTY )
)
SELECT *
  from tb
    pivot
    (
         sum( SO_QTY ) for HD in (
            [2016-05-13 2016-05-20 AXIS],
            [2016-05-10 2016-05-13 TMEH-J],
            [2016-05-12 2016-05-20 TMEH-J],
            [2016-05-17 2016-05-20 TMEH-J]
         )
    ) as pt

 

 

 

## 두번째 풀이 : 헤더값을 결과로 만들어 Union 처리 하는 방법.

;with tb
as
(
    SELECT ITEM_CD, SPEC, SO_DT, DLVY_DT, SOLD_TO_PARTY_NM, SO_QTY
    FROM (
        VALUES
            ( '41-P006-IVM', 'GAP-6 IV', '2016-05-10', '2016-05-13', 'TMEH-J', 2400 ),
            ( '41-P006-IVM', 'GAP-6 IV', '2016-05-12', '2016-05-20', 'TMEH-J', 4800 ),
            ( '41-P006-IVM', 'GAP-6 IV', '2016-05-17', '2016-05-20', 'TMEH-J', 10800 ),
            ( '41-P006-IVM', 'GAP-6 IV', '2016-05-13', '2016-05-20', 'AXIS', 2400 )

    ) AS TB ( ITEM_CD, SPEC, SO_DT, DLVY_DT, SOLD_TO_PARTY_NM, SO_QTY )
), src
as
(
    select ITEM_CD, SPEC, SO_DT + ' ' + DLVY_DT +' '+ SOLD_TO_PARTY_NM as HD, SO_QTY
    from tb
), hd1
as
(
    select ITEM_CD, SPEC, SO_DT + ' ' + DLVY_DT +' '+ SOLD_TO_PARTY_NM as HD, SO_DT
    from tb
)
, hd2
as
(
    select ITEM_CD, SPEC, SO_DT + ' ' + DLVY_DT +' '+ SOLD_TO_PARTY_NM as HD, DLVY_DT
    from tb
)
, hd3
as
(
    select ITEM_CD, SPEC, SO_DT + ' ' + DLVY_DT +' '+ SOLD_TO_PARTY_NM as HD, SOLD_TO_PARTY_NM
    from tb
)


 
select *, 1 as odr--ITEM_CD, SPEC, [2016-05-13 2016-05-20 AXIS],[2016-05-10 2016-05-13 TMEH-J],[2016-05-12 2016-05-20 TMEH-J],[2016-05-17 2016-05-20 TMEH-J]
from hd1
pivot
(
     min( SO_DT ) for HD in (
        [2016-05-13 2016-05-20 AXIS],
        [2016-05-10 2016-05-13 TMEH-J],
        [2016-05-12 2016-05-20 TMEH-J],
        [2016-05-17 2016-05-20 TMEH-J]
     )
) as pt
union

select *, 2 as odr--ITEM_CD, SPEC, [2016-05-13 2016-05-20 AXIS],[2016-05-10 2016-05-13 TMEH-J],[2016-05-12 2016-05-20 TMEH-J],[2016-05-17 2016-05-20 TMEH-J]
from hd2
pivot
(
    min( DLVY_DT ) for HD in (
        [2016-05-13 2016-05-20 AXIS],
        [2016-05-10 2016-05-13 TMEH-J],
        [2016-05-12 2016-05-20 TMEH-J],
        [2016-05-17 2016-05-20 TMEH-J]
     )
) as pt
union

select *, 3 as odr--ITEM_CD, SPEC, [2016-05-13 2016-05-20 AXIS],[2016-05-10 2016-05-13 TMEH-J],[2016-05-12 2016-05-20 TMEH-J],[2016-05-17 2016-05-20 TMEH-J]
from hd3
pivot
(
    min( SOLD_TO_PARTY_NM ) for HD in (
        [2016-05-13 2016-05-20 AXIS],
        [2016-05-10 2016-05-13 TMEH-J],
        [2016-05-12 2016-05-20 TMEH-J],
        [2016-05-17 2016-05-20 TMEH-J]
     )
) as pt
union

select ITEM_CD, SPEC,
       convert(varchar,[2016-05-13 2016-05-20 AXIS]),
       convert(varchar,[2016-05-10 2016-05-13 TMEH-J]),
       convert(varchar,[2016-05-12 2016-05-20 TMEH-J]),
       convert(varchar,[2016-05-17 2016-05-20 TMEH-J]),
       9999 as odr
from src
pivot
(
    sum( SO_QTY ) for HD in (
        [2016-05-13 2016-05-20 AXIS],
        [2016-05-10 2016-05-13 TMEH-J],
        [2016-05-12 2016-05-20 TMEH-J],
        [2016-05-17 2016-05-20 TMEH-J]
     )
) as pt
 

order by odr

 

 

 

문제1 ) http://www.sqler.com/827048#4

 

/* 100000과 가장 가까운 근사치값을 구할때 */


select n, v, abs( v - 100000 )
from (
values
  (1, 1000  ),
  (2, 2300  ),
  (3, 1000  ),
  (4, 5000  ),
  (5, 16000 ),
  (6, 54000 ),
  (7, 8200  ),
  (8, 1500  ),
  (9, 2555  )
  ) as tb( n, v )
order by 3

 

이렇게 하면 가장 가까운게 위로 올라온다.

 

 

문제2 ) http://www.sqler.com/bSQLQA/827651

 

피봇으로 데이타를 만들때 내부 데이타가 집계가 아닌 실제 원소데이타를 포함하도록 뿌려달라는 것 같다.

 


declare @ttb table
(
 TESTBENCH int,
 TESTWEEK varchar(100),
 TESTNAME varchar(100)
)
 
insert into @ttb
select *
from
(
 values
 (1, 'W1618.1', 'TEST1'),
 (1, 'W1618.1', 'TEST2'),
 (1, 'W1618.1', 'TEST3'),
 (1, 'W1618.2', 'TEST1'),
 (1, 'W1618.3', 'TEST2'),
 (2, 'W1618.2', 'TEST1'),
 (2, 'W1618.2', 'TEST3'),
 (2, 'W1618.3', 'TEST2'),
 (2, 'W1618.4', 'TEST2'),
 (2, 'W1618.4', 'TEST3')
) as tb (TESTBENCH, TESTWEEK, TESTNAME )
  


declare @TESTBENCH int
declare @W1 varchar(100), @W2 varchar(100), @W3 varchar(100), @W4 varchar(100)

declare @result table
(
 TESTBENCH int,
 [W1618.1] varchar(100),
 [W1618.2] varchar(100),
 [W1618.3] varchar(100),
 [W1618.4] varchar(100)
)
 
declare rst cursor
for
  select TESTBENCH, [W1618.1], [W1618.2], [W1618.3], [W1618.4]
  from @ttb
  pivot
  (
   count( TESTNAME ) for TESTWEEK in ( [W1618.1], [W1618.2], [W1618.3], [W1618.4] ) 
  ) as p
OPEN rst
FETCH NEXT FROM rst
INTO @TESTBENCH, @W1, @W2, @W3, @W4

WHILE @@FETCH_STATUS = 0
BEGIN
 select @W1 = '', @W2 = '', @W3 = '', @W4 = ''

 select @W1 += TESTNAME + char(10)
   from @ttb
  where TESTBENCH = @TESTBENCH
    and TESTWEEK = 'W1618.1'

    select @W2 += TESTNAME + char(10)
   from @ttb
  where TESTBENCH = @TESTBENCH
    and TESTWEEK = 'W1618.2'

    select @W3 += TESTNAME + char(10)
   from @ttb
  where TESTBENCH = @TESTBENCH
    and TESTWEEK = 'W1618.3'

      select @W4 += TESTNAME + char(10)
   from @ttb
  where TESTBENCH = @TESTBENCH
    and TESTWEEK = 'W1618.4'

 insert into @result
 select @TESTBENCH, @W1, @W2, @W3, @W4

 FETCH NEXT FROM rst
 INTO @TESTBENCH, @W1, @W2, @W3, @W4
END
CLOSE rst;
DEALLOCATE rst;

select *
from @result

 

 

커서를 이용하면 되긴 하는데 고정 컬럼으로 만들었을때 위와 같고, 가변적으로 해야 할때는 부분부분 function으로 동작할수 있게 하고 줄여서

동적 쿼리로 만들어주면 된다.

 

세번째 풀이

sqler를 들려보니 각 일별로 분을 만든게 떠있네? 음...

그래서 다시 만들어봤다. 1시간 소요 ㅠㅠ... 만들어 놓은걸 안보고 해봤음. ( 보고 싶은 유혹이... )

역시나 아직 내가 놓치는 부분들이 있네.

 

 

;with ttb as
(
  select DATEADD( HOUR, -8, convert( datetime, st )) as st, DATEADD( HOUR, -8, convert( datetime, ed)) as ed    
  from
  (
    values
     ( '2016-05-09 09:00:00', '2016-05-09 09:30:00' ),
      ( '2016-05-09 23:00:00', '2016-05-10 09:00:00' ),
      ( '2016-05-10 22:20:00', '2016-05-11 05:00:00' ),  -- 테스트를 위해 추가.
     ( '2016-05-12 22:20:00', '2016-05-15 05:00:00' )  -- 테스트를 위해 추가.
  ) as tb ( st, ed)
 /* 문제 :
  이와같은 데이터가 있을때 합산하는 시점은 오전 08시로 기준을 잡고
  2016-05-09 : 570분    (9:00 ~ 09:30 = 30분 + 23:00 ~ 익일 08:00 = 540분)
  2016-05-10 : 60분     (기준시간 08:00~ 09:00 = 60분)
  이렇게 SELECT 를 하고싶은데요.. 너무헷갈립니다 고수분들 조언부탁 드립니다.
 */
), otb ( st, ed )
as
(
 select DATEADD( hour, -8, convert( datetime, st )) as st,
        DATEADD( hour, -8, convert( datetime, ed )) as ed
   from ttb 
)
, rtb ( diff, dt )
as
(
 select DATEDIFF( day, min( st ), max( ed ) ) as diff, convert( datetime, convert( varchar(10), min( st ), 121 )) as dt
   from otb
)
, jtb ( dt1 , dt2)
as
(
 select DATEADD( Day, number, dt ) as dt1, dateadd( MILLISECOND, -2, DATEADD( Day, number + 1, dt )) as dt2
 from rtb, (
    select number
    from master.dbo.spt_values
    where name is null ) as ntb
 where ntb.number <= rtb.diff
)
select dt1, dt2, case when st is null then 0
      else
           case when dt1 <= st then st else dt1 end
    end as st
    , case when ed is null then 0
         else case when ed < dt2 then ed else dt2 end
       end as ed,
    datediff( MINUTE,
    case when st is null then 0
      else
           case when dt1 <= st then st else dt1 end
    end,
    case when ed is null then 0
         else case when ed < dt2 then ed else dt2 end
       end )
     as diff
    
  from jtb
  left
 outer join otb
    on ( otb.ed > jtb.dt1 and otb.st < jtb.dt2 ) 
  

 

 

/###############################################################################/

 

아래가 문제인데...

08시를 기준으로 시작시간, 종료시간 분(시간) 구하기.

우선 급한데로 풀이를 한다면... 아래처럼 구해보겠다. 테스트 까지 1시간 조금 안걸린듯....

 

첫번째 풀이


;with ttb as
(
 select convert( datetime, st ) as st, convert( datetime, ed) as ed    
 from
 (
  values
   ( '2016-05-09 09:00:00', '2016-05-09 09:30:00' ),
    ( '2016-05-09 23:00:00', '2016-05-10 09:00:00' ),
   ( '2016-05-10 22:20:00', '2016-05-11 05:00:00' ) -- 테스트를 위해 추가.
 ) as tb ( st, ed)
/* 문제 :
 이와같은 데이터가 있을때 합산하는 시점은 오전 08시로 기준을 잡고
 2016-05-09 : 570분    (9:00 ~ 09:30 = 30분 + 23:00 ~ 익일 08:00 = 540분)
 2016-05-10 : 60분     (기준시간 08:00~ 09:00 = 60분)
 이렇게 SELECT 를 하고싶은데요.. 너무헷갈립니다 고수분들 조언부탁 드립니다.
*/
)


select dt, sum( case when m > 0 then m else 0 end) as sum_m
from
(
 SELECT  convert( varchar(10), st, 121) as dt,
   case when DATEDIFF( DAY, st, ed ) > 0 and CONVERT( datetime, CONVERT( varchar(10), ed , 112) + ' 08:00:00' ) < ed then DATEDIFF( MINUTE, st, CONVERT( datetime, CONVERT( varchar(10), ed , 112) + ' 08:00:00' ) )
     else DATEDIFF( MINUTE, st, ed)
   end as m
   FROM  ttb

 UNION ALL

 SELECT  convert( varchar(10), ed, 121) as dt,
   DATEDIFF( MINUTE, CONVERT( datetime, CONVERT( varchar(10), ed , 112) + ' 08:00:00' ), ed ) as m
   FROM  ttb
 WHERE DATEDIFF( DAY, st, ed ) > 0 and CONVERT( datetime, CONVERT( varchar(10), ed , 112) + ' 08:00:00' ) < ed
) s
group by dt
 

 

두번재 풀이 ( 10분만에 썼음. )

 

위 식에서 다음날 08시 기준이니까 -8시간 하면 00시 정각이 되니 이것으로 시간을 구함.

 

;with ttb as
(
 select DATEADD( HOUR, -8, convert( datetime, st )) as st, DATEADD( HOUR, -8, convert( datetime, ed)) as ed    
 from
 (
  values
   ( '2016-05-09 09:00:00', '2016-05-09 09:30:00' ),
    ( '2016-05-09 23:00:00', '2016-05-10 09:00:00' )
--   ( '2016-05-10 22:20:00', '2016-05-11 05:00:00' )  -- 테스트를 위해 추가.
 ) as tb ( st, ed)
/* 문제 :
 이와같은 데이터가 있을때 합산하는 시점은 오전 08시로 기준을 잡고
 2016-05-09 : 570분    (9:00 ~ 09:30 = 30분 + 23:00 ~ 익일 08:00 = 540분)
 2016-05-10 : 60분     (기준시간 08:00~ 09:00 = 60분)
 이렇게 SELECT 를 하고싶은데요.. 너무헷갈립니다 고수분들 조언부탁 드립니다.
*/
)

select dt, sum( case when m > 0 then m else 0 end) as sum_m
from
(
 select convert( varchar(10), st, 121) as dt, DATEDIFF( MINUTE, st, ed ) - case when DATEDIFF( DAY, st, ed ) >= 1 then DATEDIFF( MINUTE, CONVERT( datetime, CONVERT( varchar(10), ed , 112) + ' 00:00:00' ), ed ) else 0 end as m
   from ttb
 union all
 select convert( varchar(10), ed, 121) as dt, DATEDIFF( MINUTE, CONVERT( datetime, CONVERT( varchar(10), ed , 112) + ' 00:00:00' ), ed )
   from ttb
  where DATEDIFF( DAY, st, ed ) > 0

) s
group by dt

 

 

 

 

 

 

 

 

  이번에 많은 일을 하는 프로시져 하나가 자꾸 실행중에 죽는다는 얘기를 들었다.

 

음... WCF 패킷이 깨지면서 오류가 뜬다.

ProtocolException ...

그런데 Sql 매니지먼트에서 돌리면 잘 돈다. ( 그러나, 메세지 창에 "경고 : 집계 또는 다른 SET ... " 이란 경고 문구가 엄청 많이 출력되었다. )

 

구글링 겁나 하다보니...

 저런 메세지가 발생할때 윈도우 시스템에 이벤트시스템과 연계되어 성능이 느려질 수 있다고 한다.

 그래서 얘기 했더니 없어지도록 쿼리를 수정하고 성능도 오류도 모두 사라졌다!!!

 

WCF  메세지 패킷 사이즈도 저거때문에 깨지는게 아니었을까???

 

참고.. http://blog.naver.com/PostView.nhn?blogId=nhsang&logNo=40127532573 


https://msdn.microsoft.com/ko-kr/library/system.servicemodel.protocolexception(v=vs.110).aspx
ProtocolException 클래스 : 데이터 전송 프로토콜이 일치하지 않아 원격 상대방과 통신할 수 없는 경우 throw되어 클라이언트에 나타나는 예외입니다.

>> https://social.msdn.microsoft.com/Forums/vstudio/en-US/77097d1f-372a-4c7d-910f-57c9ecd9c5c1/the-maximum-string-content-length-quota-8192-has-been-exceeded-while-reading-xml-data-this-quota?forum=wcf
>> https://social.msdn.microsoft.com/Forums/en-US/f5c3fdeb-65da-4d72-90eb-4c5c31e582d1/nonwcf-service-responds-with-wrong-contentlength-header-protocolexception?forum=wcf

>> WCF 설정에서 예외처리상세여부?
   http://stackoverflow.com/questions/8434206/getting-a-faultexception-when-trying-to-work-with-a-wcf-service

느룡...

 

좀더 빠른 쿼리는 없을까낭...

 

쿼리 속도가  빨라짐!!  장실에서 일보다 생각났음 ㅡ.,ㅡv

테이블 관계를 다시 확인하고, 가공해야 할 최소단위 데이타로 만들어서

58000여건에 대해 쿼리문을 적용하니 40sec -> 2sec 줄었음.

 

결과

 

 

 


;WITH CBS AS (
 SELECT *
 FROM (
 
  VALUES
 
  ('A', '코드A', '', 1),
  ('A.01', '코드A1', 'A', 2),
  ('A.02', '코드A2', 'A', 2),
  ('A.01.01', '코드A01', 'A.01', 3),
  ('A.01.02', '코드A02', 'A.02', 3)
 
 ) AS CBS ( CODE , CODENAME,  UPPER_CODE, CODE_LEVEL)
),
DETAIL AS
(
 SELECT *
 FROM (
  VALUES
 
  ('0001', '코드A.01.01.0001', 'A.01.01',  10),
  ('0002', '코드A.01.01.0002', 'A.01.01',  20),
  ('0003', '코드A.01.02.0003', 'A.01.02',  30),
  ('0004', '코드A.01.02.0004', 'A.01.02',  40),
  ('0005', '코드A.01.02.0005', 'A.01.02',  50)
 ) AS CBS ( CODE , CODENAME,  CBS_CODE, QUANTITY )
)
,
TOTAL AS
(
 SELECT SUBSTRING( CBS_CODE+ '.', 0, CHARINDEX( '.', CBS_CODE + '.')) AS CODE1 ,
   SUBSTRING( cbs_code+ '.', 0, CHARINDEX( '.', cbs_code + '.', CHARINDEX( '.', cbs_code+ '.')+1) ) as code2,
   CBS_CODE AS CODE3,
   CODE AS CODE4,
   CODENAME,
   QUANTITY  
 FROM DETAIL
)
 
SELECT CODE1 , 
  '' CODE_NAME,
  SUM(QUANTITY),
  CODE1 + '.00.00' AS ALIGN
FROM TOTAL t inner join CBS c
on  t.CODE1 = c.CODE and c.CODE_LEVEL = 1
GROUP BY CODE1

UNION ALL 
 
SELECT CODE2,
  '' CODE_NAME,
  SUM(QUANTITY)  ,
  CODE2 + '.00' AS ALIGN
FROM TOTAL t inner join CBS c
on  t.CODE2 = c.CODE and c.CODE_LEVEL = 2
GROUP BY  CODE1, CODE2
 
UNION ALL 
 
SELECT CODE3, 
  '' CODE_NAME,
  SUM(QUANTITY)  ,
  CODE3 AS ALIGN
FROM TOTAL t inner join CBS c
on  t.CODE3 = c.CODE and c.CODE_LEVEL = 3
GROUP BY CODE1, CODE2, CODE3
  
UNION ALL 
 
SELECT CODE4,
  CODENAME,
  SUM(QUANTITY) ,
  CODE3 + CODE4 AS ALIGN 
FROM TOTAL
GROUP BY CODE1,
  CODE2,
  CODE3,
  CODE4,
  CODENAME
 
ORDER BY ALIGN

 

 

sp_helptext 를 하면 애써 맞춰놓은 정렬이 다 깨져 나와서

 

그리드가 아닌 text로 바꿔 실행해서 본다거나 해당 프로시져를 찾아서 수정 눌러서 본다거나...

 

귀찮아진다.

 

기존껀 긴건 짤린다 해서 = varchar( max )

 

sp_helptext를 수정하였음.

 

아래 파란색 글씨만 추가해서 새로 등록함.

 

 1.  스크립트 생성 [ SP_HELPTXT ]

USE [master]
GO
/****** Object:  StoredProcedure [dbo].[SP_HELPTXT]    Script Date: 11/22/2012 11:55:45 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER procedure [dbo].[SP_HELPTXT] 
 @objname nvarchar(776) 
   ,@columnname sysname = NULL 
as 
 
set nocount on 
 
declare @dbname sysname 
,@objid int 
,@BlankSpaceAdded   int 
,@BasePos       int 
,@CurrentPos    int 
,@TextLength    int 
,@LineId        int 
,@AddOnLen      int 
,@LFCR          int --lengths of line feed carriage return 
,@DefinedLength int 
 
/* NOTE: Length of @SyscomText is 4000 to replace the length of 
** text column in syscomments. 
** lengths on @Line, #CommentText Text column and 
** value for @DefinedLength are all 255. These need to all have 
** the same values. 255 was selected in order for the max length 
** display using down level clients 
*/ 
,@SyscomText nvarchar(4000) 
,@Line          nvarchar(255) 
 
select @DefinedLength = 255 
select @BlankSpaceAdded = 0 /*Keeps track of blank spaces at end of lines. Note Len function ignores 
                             trailing blank spaces*/ 
CREATE TABLE #CommentText 
(LineId int 
 ,Text  nvarchar(255) collate database_default) 
 
/* 
**  Make sure the @objname is local to the current database. 
*/ 
select @dbname = parsename(@objname,3) 
if @dbname is null 
 select @dbname = db_name() 
else if @dbname <> db_name() 
        begin 
                raiserror(15250,-1,-1) 
                return (1) 
        end 
 
/* 
**  See if @objname exists. 
*/ 
select @objid = object_id(@objname) 
if (@objid is null) 
        begin 
  raiserror(15009,-1,-1,@objname,@dbname) 
  return (1) 
        end 
 
-- If second parameter was given. 
if ( @columnname is not null) 
    begin 
        -- Check if it is a table 
        if (select count(*) from sys.objects where object_id = @objid and type in ('S ','U ','TF'))=0 
            begin 
                raiserror(15218,-1,-1,@objname) 
                return(1) 
            end 
        -- check if it is a correct column name 
        if ((select 'count'=count(*) from sys.columns where name = @columnname and object_id = @objid) =0) 
            begin 
                raiserror(15645,-1,-1,@columnname) 
                return(1) 
            end 
    if (ColumnProperty(@objid, @columnname, 'IsComputed') = 0) 
  begin 
   raiserror(15646,-1,-1,@columnname) 
   return(1) 
  end 
 
        declare ms_crs_syscom  CURSOR LOCAL 
        FOR select text from syscomments where id = @objid and encrypted = 0 and number = 
                        (select column_id from sys.columns where name = @columnname and object_id = @objid) 
                        order by number,colid 
        FOR READ ONLY 
 
    end 
else if @objid < 0 -- Handle system-objects 
 begin 
  -- Check count of rows with text data 
  if (select count(*) from master.sys.syscomments where id = @objid and text is not null) = 0 
   begin 
    raiserror(15197,-1,-1,@objname) 
    return (1) 
   end 
    
  declare ms_crs_syscom CURSOR LOCAL FOR select text from master.sys.syscomments where id = @objid 
   ORDER BY number, colid FOR READ ONLY 
 end 
else 
    begin 
        /* 
        **  Find out how many lines of text are coming back, 
        **  and return if there are none. 
        */ 
        if (select count(*) from syscomments c, sysobjects o where o.xtype not in ('S', 'U') 
            and o.id = c.id and o.id = @objid) = 0 
                begin 
                        raiserror(15197,-1,-1,@objname) 
                        return (1) 
                end 
 
        if (select count(*) from syscomments where id = @objid and encrypted = 0) = 0 
                begin 
                        raiserror(15471,-1,-1,@objname) 
                        return (0) 
                end 
 
  declare ms_crs_syscom  CURSOR LOCAL 
  FOR select text from syscomments where id = @objid and encrypted = 0 
    ORDER BY number, colid 
  FOR READ ONLY 
 
    end 
 
/* 
**  else get the text. 
*/ 
select @LFCR = 2 
select @LineId = 1 
 
 
OPEN ms_crs_syscom 
 
FETCH NEXT from ms_crs_syscom into @SyscomText 
 
WHILE @@fetch_status >= 0 
begin 
 
    select  @BasePos    = 1 
  select  @CurrentPos = 1 
    select  @TextLength = LEN(@SyscomText) 
 
    WHILE @CurrentPos  != 0 
    begin 
        --Looking for end of line followed by carriage return 
        select @CurrentPos =   CHARINDEX(char(13)+char(10), @SyscomText, @BasePos) 
 
        --If carriage return found 
        IF @CurrentPos != 0 
        begin 
            /*If new value for @Lines length will be > then the 
            **set length then insert current contents of @line 
            **and proceed. 
            */ 
            while (isnull(LEN(@Line),0) + @BlankSpaceAdded + @CurrentPos-@BasePos + @LFCR) > @DefinedLength 
            begin 
                select @AddOnLen = @DefinedLength-(isnull(LEN(@Line),0) + @BlankSpaceAdded) 
                INSERT #CommentText VALUES 
                ( @LineId, 
                  isnull(@Line, N'') + isnull(SUBSTRING(@SyscomText, @BasePos, @AddOnLen), N'')) 
                select @Line = NULL, @LineId = @LineId + 1, 
                       @BasePos = @BasePos + @AddOnLen, @BlankSpaceAdded = 0 
            end 
            select @Line    = isnull(@Line, N'') + isnull(SUBSTRING(@SyscomText, @BasePos, @CurrentPos-@BasePos + @LFCR), N'') 
            select @BasePos = @CurrentPos+2 
            INSERT #CommentText VALUES( @LineId, @Line ) 
            select @LineId = @LineId + 1 
            select @Line = NULL 
        end 
        else 
        --else carriage return not found 
        begin 
            IF @BasePos <= @TextLength 
            begin 
                /*If new value for @Lines length will be > then the 
                **defined length 
                */ 
                while (isnull(LEN(@Line),0) + @BlankSpaceAdded + @TextLength-@BasePos+1 ) > @DefinedLength 
                begin 
                    select @AddOnLen = @DefinedLength - (isnull(LEN(@Line),0) + @BlankSpaceAdded) 
                    INSERT #CommentText VALUES 
                    ( @LineId, 
                      isnull(@Line, N'') + isnull(SUBSTRING(@SyscomText, @BasePos, @AddOnLen), N'')) 
                    select @Line = NULL, @LineId = @LineId + 1, 
                        @BasePos = @BasePos + @AddOnLen, @BlankSpaceAdded = 0 
                end 
                select @Line = isnull(@Line, N'') + isnull(SUBSTRING(@SyscomText, @BasePos, @TextLength-@BasePos+1 ), N'') 
                if LEN(@Line) < @DefinedLength and charindex(' ', @SyscomText, @TextLength+1 ) > 0 
                begin 
                    select @Line = @Line + ' ', @BlankSpaceAdded = 1 
                end 
            end 
        end 
    end 
 
 FETCH NEXT from ms_crs_syscom into @SyscomText 
end 
 
IF @Line is NOT NULL 
    INSERT #CommentText VALUES( @LineId, @Line ) 

declare @lineNo int = 0;
declare @lineCnt int = 0;
declare @printtext varchar(max);
select @lineCnt = COUNT( LineId ) from #CommentText;
while( @lineNo < @lineCnt )
begin
 set @lineNo = @lineNo + 1;
 
 select @printtext = Text from #CommentText
 where LineId = @lineNo ;
 
 print( @printtext );
end
CLOSE  ms_crs_syscom 
DEALLOCATE  ms_crs_syscom 
 
DROP TABLE  #CommentText 
 
return (0) -- sp_helptext 

 

 

 

 

2. 프로시져를 시스템프로시져로 만든다.

USE [master]
GO
exec sp_ms_marksystemobject 'sp_helptxt'

 

3. 단축키에 등록해서 사용하면

 

print 되기때문에 탭유지되면서 잘 나온다 복사 해서 쓰면 됨.

 

 

 

 

오늘 두개의 데이타 베이스의 스키마 비교 쿼리를 만들다 보니..

 

한쪽은 있고 다른 한쪽은 없을 때를 위해 테이블을 복제를 자동화 하려고 했는데...

 

쿼리 한방에 안되네! 

 

  SELECT * INTO 대상DB.dbo.테이블명 FROM 소스DB.dbo.테이블명 where 1 = 2

 

하면 복제는 되는데 키가 복제가 안됨을 확인.

 

 그래서 만들었다. 우선 mssql 스튜디오에서 만들어지는 스크립트와 같이 만들어 보고

 

고정 타입은 아닌것 같은데 군데 군데 하드 코딩이 되있어서 전혀 다르게 동작 가능.

 

음.. ms-sql에서 사용하는 테이블 -> Create 스크립트 쿼리 같은걸 이용하는건 못찾았다.

 

 

declare @tableName nvarchar(775) =QUOTENAME( SCHEMA_NAME() )+'.'+ QUOTENAME(  테이블명  )
declare @Script varchar(max) = ''
declare @FKScript varchar(max) = ''
declare @ctrl varchar(2) = char(13)

declare @type1 varchar(100) = 'char, varchar'
declare @type2 varchar(100) = 'nchar, nvarchar '
declare @type3 varchar(100) = 'numeric,decimal'
 
set @Script = 'CREATE TABLE ' + @tableName + '(' + @ctrl

-- Columns
select @Script += ' '+ QUOTENAME( c.name ) + ' '+ QUOTENAME( TYPE_NAME( system_type_id ) )
  + case
    when CHARINDEX( TYPE_NAME(system_type_id), @type1 , 0) > 0 then '('+ case when c.max_length = -1 then

'max' else CAST( c.max_length as varchar(20) ) end +')'
    when CHARINDEX( TYPE_NAME(system_type_id), @type2 , 0) > 0 then '('+ case when c.max_length = -1 then

'max' else CAST( c.max_length/2 as varchar(20) ) end +')'
    when CHARINDEX( TYPE_NAME(system_type_id), @type3 , 0) > 0 then '('+ CAST( c.precision as varchar(20) )

+ ',' + CAST( c.scale as varchar(20) )+')'
    else '' end
  + ' '+  case when is_nullable = 1 then '' else 'NOT' end + ' NULL,' + @ctrl
from sys.tables t inner join sys.columns c
on  t.object_id = c.object_id
where t.object_id = OBJECT_ID( @tableName )

-- 콤마 제거
set @Script = left( @Script , datalength( @Script )-  datalength( @ctrl ) - datalength( ',') ) + @ctrl

-- Primary Key 생성
select @Script += ' CONSTRAINT ' + QUOTENAME( name ) + ' PRIMARY KEY CLUSTERED '+ @ctrl
from sys.key_constraints
where parent_object_id = object_id( @tableName ) and [TYPE] = 'PK'

select @Script += ' (' + @ctrl

select  @Script += '  '+ QUOTENAME( c.name )+ ' ASC,' + @ctrl
from sys.index_columns i inner join sys.key_constraints k
on  i.object_id = k.parent_object_id
inner join sys.columns c
on  i.object_id = c.object_id and i.column_id = c.column_id
inner join sys.indexes ii
on  i.object_id = ii.object_id and i.index_id = ii.index_id
where parent_object_id = object_id( @tableName ) and k.[TYPE] = 'PK'
 
-- 콤마 제거
set @Script = left( @Script , datalength( @Script )-  datalength( @ctrl ) - datalength( ',') ) + @ctrl
 
select @Script += ' ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,

ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]' + @ctrl
select @Script += ') ON [PRIMARY]' + @ctrl
select @Script += 'GO' + @ctrl

-- Foreign Key 추가
select @FKScript += 'ALTER TABLE '+QUOTENAME( SCHEMA_NAME() )+'.'+ QUOTENAME( OBJECT_NAME( fkeyid )) + ' WITH CHECK ADD 

CONSTRAINT '+ QUOTENAME( OBJECT_NAME( constid ) ) + ' FOREIGN KEY ('+  QUOTENAME( cf.name ) + ')'+ @ctrl
  + 'REFERENCES '+QUOTENAME( SCHEMA_NAME() )+'.'+ QUOTENAME( OBJECT_NAME( rkeyid )) + ' ('+ QUOTENAME(

cr.name )+')'+ @ctrl
  + 'GO' + @ctrl + @ctrl
  + case when parent_object_id is null then 'ALTER TABLE '+QUOTENAME( SCHEMA_NAME() )+'.'+ QUOTENAME(

OBJECT_NAME( fkeyid )) + ' CHECK CONSTRAINT '+ QUOTENAME( OBJECT_NAME( constid ) ) + 'GO' + @ctrl + @ctrl else '' end
from sys.sysforeignkeys f
left
outer join sys.columns cf
on  f.fkeyid = cf.object_id and f.fkey = cf.column_id
left
outer join sys.columns cr
on  f.rkeyid = cr.object_id and f.rkey = cr.column_id

left    -- CHECK KEY < 참조키만 된 컬럼 >
outer join
(
 select  k.parent_object_id, i.column_id
 from sys.index_columns i inner join sys.key_constraints k
 on i.object_id = k.parent_object_id
 and i.object_id = OBJECT_ID( @tableName )     
) t
on  f.fkeyid  = t.parent_object_id  and f.fkey = t.column_id

where fkeyid = OBJECT_ID( @tableName )

 

print @Script
print @FKScript