최근 포토로그


인도 AirTell 통신비 미분류

유심빼고 통신비만 보면 하루 1.5기가에 200루피다 28일 쓸수 있는 것이고...

이거 우리돈으로 환산하면 약, 3360원 정도네....

씨불 디게 싸네.

한국 저렴한 통신사 알아보면 이거 제3통신사를 써도 2배이상이다.

그러고보면 한국 통신비 싸다는 말 개구라임.

인도라서 그렇다고?

그럼 할 말 없지머.





MSSQL 임시테이블 활용하기 MSSQL과 ORACLE

물론 테이블변수가 작게 쓸려고 하거나 컴파일 하지 않으려고 하면 쓰임새가 많다.

하지만, 
임시테이블 (#)이 붙은 테이블은 쓰기에 따라서 아름다운 결과물을 만들어 낼수 있다.

MSSQL 임시테이블은 #을 하나만 쓴다면 자기영역 내에서는 어디에서든 쓸수 있다.

즉, 내부 프로시저 안과 내가 호출하는 프로시저내에서는 자유롭게 부를 수 있다는 거다.

즉,

아래 셈플을 보자

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

-- DROP PROC dbo.usp_TableVar
go
CREATE PROC dbo.usp_TableVar

AS

create table #Tb_test 
(

OrderID int identity(1,1) PRIMARY KEY NONCLUSTERED
, OrderDate datetime CHECK (OrderDate >= '1900-01-01')

)

INSERT INTO #Tb_test values ('20180101')
INSERT INTO #Tb_test values ('19910101')

--SELECT TOP 10 OrderDate FROM Orders --OrderID 컬럼은 지정할 필요 없다.


UPDATE #Tb_test SET OrderDate = OrderDate + 1

DELETE #Tb_test WHERE OrderDate > '1996-07-10'

exec usp_TableVar2

SELECT * FROM #Tb_test

GO



-- DROP PROC dbo.usp_TableVar2
go
CREATE PROC dbo.usp_TableVar2

AS


INSERT INTO #Tb_test values ('20180102')
INSERT INTO #Tb_test values ('19910103')
exec usp_TableVar3


GO

-- DROP PROC dbo.usp_TableVar3
go
CREATE PROC dbo.usp_TableVar3

AS


INSERT INTO #Tb_test values ('20180105')
INSERT INTO #Tb_test values ('19910106')

GO

EXEC dbo.usp_TableVar


-- DROP PROC dbo.usp_TableVar
-- DROP PROC dbo.usp_TableVar2
-- DROP PROC dbo.usp_TableVar3

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

usp_TableVar 프로시저가 usp_TableVar2를 부르고 usp_TableVa3을 부른다.

그럼에도 임시테이블 
#Tb_test 에는 접근 가능하고, 다 추가/수정/삭제 되다.


쿼리결과에 TAB, LF 등이 표결과에서 안 나올때 MSSQL과 ORACLE

참 간단한 거였는데 이제 알았다.



첫번째꺼에 보면 표로 결과를 보내면 텝키나 라인조정이 이상하게 되어서 결과가 space한개로 바뀌어서
나중에 복사하면 결과물이 이상하게 된다.


즉 

이런 식으로 텝이 있으면 이걸 복사하는 과정에서 mssql은 텝무시가 디폴트로 되어있어서 결국 

이런 방식으로 텝이 없어지면서 거기에 스페이스가 알아서 먹히면서 줄 정렬이 지독하게 이상하게 되는 것이다.

이거를 막기 위해서는 이전에는 짜증나게도 "텍스트 결과로 표시"를 사용했다.

즉,
이렇게 하면 출력이 잘되었지만, 
나는 항상 표로 결과물을 도출하는데, SP 내의 결과를 보기위해서 자꾸 왔다갔다 해야 하는 것 때문에 짜증 지수가 MAX였다.



그런데 오늘 SSMS 설정 좀 건드리다가 알아낸 사실

"복사 또는 저장 시 CR/LF 보존"
이라는 게 결국 그걸 잘 해주는 거였네.

이렇게 하고 새탭 열어서 이래저래 테스트 해보니
표결과는 이상하게 보여도, 복사&붙여넣기를 하면 TAB키도 잘 표시되고 이쁘게 나온다.

이런거 정말 필요했는데 아직도 못했던 내가 미워





MSSQL 의 SSMS 에서 암호저장이 안될 때,

보안 문제는 있지만 저장 안되는 버그가 나를 괴롭힌다.

그래서 구글링해보니


C:\Users\사용자\AppData\Roaming\Microsoft\Microsoft SQL Server\140\Tools\Shell
밑의 파일을 삭제하고 다시  ssms 껏다가 켜라고 되어있더라.

해보니 잘된다.


단, 이전 저장한 로그들 싹다 날라간다.


저 위의 
140은 내가 14버전을 쓰고 있어서 그렇다.

버전별로 안에 들어가 있는 파일이 조금 다르더라.

암튼 그쪽 파일 지우면 만사 OK


심심해서 써보는 오픈엑스컴 TFTD - 슈퍼휴먼 난이도. 게임?

예전에 엑스컴 TFTD 를 슈퍼휴먼 난이도로 클리어한 기억이 있다.

근데 생각해보면 이전 엑스컴의 TFTD는 슈퍼휴먼 난이도라고 해도, 세이브모드가 있었기 때문에 내가 클리어를 쉽게(?) 했던 기억이 있다.

그런에 오픈엑스컴(OpenXcom)는 아이언모드가 있다.

한마디로 저장질(?)을 못하는 버전이다.

근데 이 아이언모드로 하면 빡지는 부분이 밤에 공격하면 시야가 극도로 좁아지는 단점 때문에
낮에 접근하려고 기다려야 하는데, 항구미션, 배미션은 시간지나면 사라지기 때문에 대중 짐작해서 출발해야 한다.

그렇다고 웨이포인트에 기다려도 잘 사라지기 때문에 시간이 빡빡할 경우 그냥 감으로 출동해버리는 수가 많다.
그러다보면 어두운데서 조명탄 던지면서 해야 한다.

예전 처음했던 슈퍼휴먼의 난이도는 고폭탄을 때려도 섹토이드가 죽지 않는 경우도 있었다. - 아니 좀 있었다. - 
그리고 이놈들 흥분하면 심심하면 외계수류탄을 까서 작살나는 경우가 너무 많았다.

다행히(?) 오픈엑스컴에서는 수류탄은 잘 안쓰는데, 갑자기 디스트럽터 펄스 런처를 잘(?) 발사해서 몰살 당하는 경우가 잦더라.

거기다가 오픈엑스컴에서는 초반 2~3월에도 외계인들이 갑자기 기지로 처들어오는 경우가 생겼다.
아예 소닉수류탄 정도만 개발했는데 외계인이 처들어오면 그게 상대가 되냐?

거기다가 5개월 넘어가면 소닉캐논도 개발 안되었는데, 랍스터가 처들어 와서 도저히 답이 없는 경우도 생겼다.


허.... 어쨌거나 오픈엑스컴 TFTD 2018년 9월버전은 수퍼휴면 아이언모드로 할려니 진짜 박시게 해야 한다는 걸 깨달았다.

몇번 당하다가 
지금 3월까지 진행했는데 이거 성공할 것 같다.

나중에 유투브 방송을 할수 있다면 이거 라이브로 방영하는 것도 좋은 거 같다. 
ㅎㅎㅎ


SP_HELPTEXT의 고질적인 문제에 대한 고찰 MSSQL과 ORACLE

내가 여기에 SP_HELPTEXT 에 대한 글만 여러 개 썼었는데, 항상 문제가 발생하였다.

왜 이런 귀찮은 일을 하는지 물어본다면 추가 라인이 갑자기 생기는 문제 때문이다.

내 작업의 특성상 MSSQL 스토어드프로시저를 많이 쓰는데, 
SSMS를 사용하여 프로시저 수정 을 클릭했을 때랑, SP_HELPTEXT를 사용하여 프로시저를 불렀을때랑 결과물이 다르게 나타나는 문제 때문이다.


이게 한번만 수정하면 상관없는데, 여러번 수정을 거치면 기하급수적으로 이쁘게 만들었던 라인들이 엉망이 되어간다는 점이다.

물론 다른 툴을 사용하면 되겠지만 나는 MSSQL 순정, 거기에 SSMS를 사용하므로 SP_HELPTEXT를 수정하지 않으면
결국 에러를 발생시키거나 아니면 엄청나게 이상한 라인을 참으며 작업을 해야 한다.

그 결과의 셈플 화면이 이건데

위에처럼 "WHERE" 부분이 갑자기 튀어나와서 라인이 엉클러지는 문제이다.


그래서 수정을 거치게 되었는데 그게 SP_HELPTEXT2 인데,
문제는 내가 CREATE PROCEDURE 라는 글자를 매번 ALTER PROCEDURE 라는 글자로 바꾸기 싫다는 거다.

그레서 결과물을 커서로 돌려서 첫째라인을 바꾼 후에 PRINT를 출력하였더니
빈칸에 공백이 한개씩 찍혀나오는 버그를 발겼했다.
씨붕
아래 화면에 적나라하게 나타난다.
스페이스가 한칸씩 있다는 말이지. 또한 PRINT의 특성상 맨 마지막 라인 이후에 엔터키가 하나가 먹힌다.
이쯤되면 짜증이 좀 난다.

그래서 어쩔 수 없이 PRINT 부분을 다시 테이블에 넣고 표형태로 결과물을 찍어야 내가 원하는 결과물을 얻어낼 수 있다는 것을 발견했다.


아름다운 결과물을 먼저 감상하자.
이 화면에서는 잘 안보이지만, 빈라인에 공백 1개씩 추가되는 것도 없고, CREATE PROC를 ALTER PROC로 바꾸어주고
그리고 맨 마지막 라인도 깔끔하게 끝나는 버전으로 완성했다.


기뻐서 이것을 최종버전으로 배포합니다.

쌩유

아래부분은 프로시저입니다. ==================================>
ALTER PROCEDURE SP_HELPTEXT2 (@ProcName NVARCHAR(256))
AS
BEGIN
    SET NOCOUNT ON
    DECLARE @SEQ INT
    DECLARE @TEXT NVARCHAR(4000)

    DECLARE @PROC_TABLE TABLE (X1  NVARCHAR(MAX))


    DECLARE @Proc NVARCHAR(MAX)
    DECLARE @Procedure NVARCHAR(MAX)
    DECLARE @ProcLines TABLE (PLID INT IDENTITY(1,1), Line NVARCHAR(MAX))

    DECLARE @NEW_ProcLines TABLE (PLID INT IDENTITY(1,1), Line NVARCHAR(MAX))

    SELECT @Procedure = 'SELECT DEFINITION FROM ['+db_name()+'].SYS.SQL_MODULES WHERE OBJECT_ID = OBJECT_ID('''+@ProcName+''')'

    insert into @PROC_TABLE (X1)
          exec  (@Procedure)

    SELECT @Proc=X1 from @PROC_TABLE

    WHILE CHARINDEX(CHAR(13)+CHAR(10),@Proc) > 0
    BEGIN
          INSERT @ProcLines
          SELECT LEFT(@Proc,CHARINDEX(CHAR(13)+CHAR(10),@Proc)-1)
          SELECT @Proc = SUBSTRING(@Proc,CHARINDEX(CHAR(13)+CHAR(10),@Proc)+2,LEN(@Proc))
    END
    --* inserts last line
    INSERT @ProcLines
    SELECT @Proc ;

    --SELECT Line FROM @ProcLines ORDER BY PLID


    DECLARE SCRIPTCURSOR9 CURSOR LOCAL FORWARD_ONLY STATIC FOR
        SELECT PLID, Line FROM @ProcLines ORDER BY PLID

    OPEN SCRIPTCURSOR9

    FETCH NEXT FROM SCRIPTCURSOR9 INTO @SEQ, @TEXT

    WHILE @@FETCH_STATUS = 0
    BEGIN
        IF @SEQ <= 1
        BEGIN
            SET @TEXT = REPLACE(@TEXT, 'CREATE PROC', 'ALTER PROC')
            SET @TEXT = REPLACE(@TEXT, 'CREATE FUNC', 'ALTER FUNC')
            SET @TEXT = REPLACE(@TEXT, 'CREATE VIEW', 'ALTER VIEW')
        END
        insert into @NEW_ProcLines 
               SELECT @TEXT
        --PRINT @TEXT

        FETCH NEXT FROM SCRIPTCURSOR9 INTO @SEQ, @TEXT
    END

    CLOSE SCRIPTCURSOR9
    DEALLOCATE SCRIPTCURSOR9

    SELECT Line FROM @NEW_ProcLines ORDER BY PLID

    --DROP TABLE  @ProcLines

END
========================================================

맘 놓고 쓰시라



귀찮아서 쓰는 MSSQL 테이블, SP, 칼럼, 뷰 관련 목록 정보 조회 MSSQL과 ORACLE

--테이블 목록 가져오기:
SELECT * FROM sysobjects WHERE xtype='U'

--뷰:
SELECT * FROM sysobjects WHERE xtype='V'

--프로시져:
SELECT * FROM sysobjects WHERE xtype='P'


--테이블 리스트
SELECT * FROM  INFORMATION_SCHEMA.TABLES
--뷰 리스트
SELECT * FROM  INFORMATION_SCHEMA.VIEWS
--컬럼 리스트
SELECT * FROM  INFORMATION_SCHEMA.COLUMNS
--컬럼 키값
SELECT * FROM  INFORMATION_SCHEMA.KEY_COLUMN_USAGE

--프로시져
SELECT * FROM INFORMATION_SCHEMA.ROUTINES
--프로시져 파라메타값
SELECT * FROM  INFORMATION_SCHEMA.PARAMETERS

 

--컬럼 정보 가져오기
SELECT
 A.TABLE_CATALOG
 ,A.TABLE_NAME
 ,A.ORDINAL_POSITION
 ,A.COLUMN_NAME
 ,A.DATA_TYPE
 ,ISNULL(A.CHARACTER_MAXIMUM_LENGTH,'')
 ,ISNULL(A.NUMERIC_PRECISION,'')
 ,A.IS_NULLABLE
 ,ISNULL(A.COLUMN_DEFAULT,'')
 ,ISNULL(B.CONSTRAINT_NAME,'')
 ,ISNULL(A.CHARACTER_SET_NAME,'')
 ,ISNULL(A.COLLATION_NAME,'')
 ,CASE WHEN ISNULL(C.NAME,'') = '' THEN '' ELSE 'Identity' END auto
FROM 
 INFORMATION_SCHEMA.COLUMNS A
 LEFT OUTER JOIN
 INFORMATION_SCHEMA.KEY_COLUMN_USAGE B
 ON A.TABLE_NAME = B.TABLE_NAME 
 AND A.COLUMN_NAME = B.COLUMN_NAME
 LEFT OUTER JOIN
 syscolumns C 
 ON C.ID = object_id(A.TABLE_NAME) AND A.COLUMN_NAME = C.NAME AND C.COLSTAT & 1 = 1 
WHERE
 A.TABLE_NAME = '테이블명'
ORDER BY A.ORDINAL_POSITION


SP_HELPTEXT 의 완성판( 줄이 밀리는 현상 해결) MSSQL과 ORACLE

SP_HELPTEXT 를 쓰다보면 자꾸 라인이 깨지는 현상이 가끔 가다가 발견한다.

이게 현상의 원인이 무엇인지 알아내지 못해서 몇년동안 고생해서 
차라리 SSMS에서 그냥 수정을 누르거나 라인을 일일이 다시 조정해주고 실행해주는 번거로움을 겪어야 했다.

이거 SP 많이 다루는 사람은 알겠지만, 정말 큰 스트레스다.

그래서 구글링은 몇년동안 지속적으로 한 결과 결국 답을 찾아냈다.


찬양하라 구글신이여!!!!


이제 드디어 SP_HELPTXTX의 버그 없는 판을 만든 것이다.

SP 참조 (참고로 여기 버전은 ALTER PROC부분으로 수정한다든지, 콘솔창에 찍어주는 부분도 포함되었다.
뜯어보시고 수정하시라.


==================================================
CREATE PROCEDURE SP_HELPTEXT2
( @PROCNAME NVARCHAR(256)
)
AS
BEGIN
    SET NOCOUNT ON
    DECLARE @PROC_TABLE TABLE (X1  NVARCHAR(MAX))

    DECLARE @PROC NVARCHAR(MAX)
    DECLARE @PROCEDURE NVARCHAR(MAX)
    DECLARE @PROCLINES TABLE (PLID INT IDENTITY(1,1), LINE NVARCHAR(MAX))
    DECLARE @SEQ INT
    DECLARE @TEXT NVARCHAR(4000)

    SELECT @PROCEDURE = 'SELECT DEFINITION FROM ['+DB_NAME()+'].SYS.SQL_MODULES WHERE OBJECT_ID = OBJECT_ID('''+@PROCNAME+''')'

    INSERT INTO @PROC_TABLE (X1)
          EXEC  (@PROCEDURE)

    SELECT @PROC=X1 FROM @PROC_TABLE

    WHILE CHARINDEX(CHAR(13)+CHAR(10),@PROC) > 0
    BEGIN
          INSERT @PROCLINES
          SELECT LEFT(@PROC,CHARINDEX(CHAR(13)+CHAR(10),@PROC)-1)
          SELECT @PROC = SUBSTRING(@PROC,CHARINDEX(CHAR(13)+CHAR(10),@PROC)+2,LEN(@PROC))
    END
    --* INSERTS LAST LINE
    INSERT @PROCLINES
    SELECT @PROC ;
    -- 이부분을 넣으면 테이블그리드로 나온다.
    --SELECT LINE FROM @PROCLINES ORDER BY PLID


    DECLARE SCRIPTCURSOR9 CURSOR LOCAL FORWARD_ONLY STATIC FOR
        SELECT PLID, LINE FROM @PROCLINES ORDER BY PLID

    OPEN SCRIPTCURSOR9

    FETCH NEXT FROM SCRIPTCURSOR9 INTO @SEQ, @TEXT

    WHILE @@FETCH_STATUS = 0
    BEGIN
        -- 1번라인에 CREATE 부분을 수정
        IF @SEQ <= 1
        BEGIN
            SET @TEXT = REPLACE(@TEXT, 'CREATE PROC', 'ALTER PROC')
            SET @TEXT = REPLACE(@TEXT, 'CREATE FUNC', 'ALTER FUNC')
            SET @TEXT = REPLACE(@TEXT, 'CREATE VIEW', 'ALTER VIEW')
        END
        PRINT @TEXT

        FETCH NEXT FROM SCRIPTCURSOR9 INTO @SEQ, @TEXT
    END

    CLOSE SCRIPTCURSOR9
    DEALLOCATE SCRIPTCURSOR9

    --DROP TABLE  @PROCLINES

END

SSMS(SQL Server Management Studio) 단축키 변경하기 MSSQL과 ORACLE

MSSQL 의 쿼리서버관리스튜디오는 - 왜 이리 적당한 한글명칭이 없는거야? -
단축키 변경이 좀 특이하다.

예전에 주석처리하기 단축키가 Ctrl+Shift+C, CTRL+Shift+R
이었는데, 이제는 너무 달라져서 두번, 세번 키를 타이핑해야 해서 내가 짜증나서 

Ctrl+Shift+>
Ctrl+Shift+<

로 바꾸기로 했다.

근데 이게 좀 복잡하니 자세히 써본다.

먼저 옵션->환경->키보드로 가면 
편집.선택영역을주석으로처리 가 보인다.


제거를 두번 누르기

그러면 바로가기 키 누리기에서 단축키 넣고 할당 버튼



간만에 xcom2(TFTD)를 superhuan, ironman 으로 했다. 게임?

간만에 했는데, ironman 이라서 save Load 짓거리를 못하니깐, 조심스럽게 하게 되더라

초반에 Deep one Terror 놈을 못잡아서 고생했는데,
lobster man 나왔으니 10분의 1 정도는 깬거 같다.

근데 이정도 되면 귀찮을 뿐.

mssql에서 table 스크립트 뽑아내기 MSSQL과 ORACLE

하다보면 알겠지만, create table 스크립트 뽑아내는게 정말 귀찮다.
그래서 구글링을 했다.

나는 dbo나 이런거 붙는 거 극혐하므로, 여러가지 해본 결과 다음의 프로시저가 가장 아름답다는 결론이 났다.

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

CREATE procedure USP_CREATE_TABLE_SCRIPT
      @table_name SYSNAME
AS
BEGIN
--DECLARE @table_name SYSNAME
--SELECT @table_name = 'dbo.omm_config'

DECLARE
      @object_name SYSNAME
    , @object_id INT

SELECT
      @object_name = o.name
    , @object_id = o.[object_id]
FROM sys.objects o WITH (NOWAIT)
JOIN sys.schemas s WITH (NOWAIT) ON o.[schema_id] = s.[schema_id]
WHERE o.name = @table_name
    AND o.[type] = 'U'
    AND o.is_ms_shipped = 0

DECLARE @SQL NVARCHAR(MAX) = ''

;WITH index_column AS
(
    SELECT
          ic.[object_id]
        , ic.index_id
        , ic.is_descending_key
        , ic.is_included_column
        , c.name
    FROM sys.index_columns ic WITH (NOWAIT)
    JOIN sys.columns c WITH (NOWAIT) ON ic.[object_id] = c.[object_id] AND ic.column_id = c.column_id
    WHERE ic.[object_id] = @object_id
),
fk_columns AS
(
     SELECT
          k.constraint_object_id
        , cname = c.name
        , rcname = rc.name
    FROM sys.foreign_key_columns k WITH (NOWAIT)
    JOIN sys.columns rc WITH (NOWAIT) ON rc.[object_id] = k.referenced_object_id AND rc.column_id = k.referenced_column_id
    JOIN sys.columns c WITH (NOWAIT) ON c.[object_id] = k.parent_object_id AND c.column_id = k.parent_column_id
    WHERE k.parent_object_id = @object_id
)
SELECT @SQL = 'CREATE TABLE ' + @object_name + CHAR(13) + '(' + CHAR(13) + STUFF((
    SELECT CHAR(9) + ', [' + c.name + '] ' +
        CASE WHEN c.is_computed = 1
            THEN 'AS ' + cc.[definition]
            ELSE UPPER(tp.name) +
                CASE WHEN tp.name IN ('varchar', 'char', 'varbinary', 'binary', 'text')
                       THEN '(' + CASE WHEN c.max_length = -1 THEN 'MAX' ELSE CAST(c.max_length AS VARCHAR(5)) END + ')'
                     WHEN tp.name IN ('nvarchar', 'nchar', 'ntext')
                       THEN '(' + CASE WHEN c.max_length = -1 THEN 'MAX' ELSE CAST(c.max_length / 2 AS VARCHAR(5)) END + ')'
                     WHEN tp.name IN ('datetime2', 'time2', 'datetimeoffset')
                       THEN '(' + CAST(c.scale AS VARCHAR(5)) + ')'
                     WHEN tp.name = 'decimal'
                       THEN '(' + CAST(c.[precision] AS VARCHAR(5)) + ',' + CAST(c.scale AS VARCHAR(5)) + ')'
                    ELSE ''
                END +
                CASE WHEN c.collation_name IS NOT NULL THEN ' COLLATE ' + c.collation_name ELSE '' END +
                CASE WHEN c.is_nullable = 1 THEN ' NULL' ELSE ' NOT NULL' END +
                CASE WHEN dc.[definition] IS NOT NULL THEN ' DEFAULT' + dc.[definition] ELSE '' END +
                CASE WHEN ic.is_identity = 1 THEN ' IDENTITY(' + CAST(ISNULL(ic.seed_value, '0') AS CHAR(1)) + ',' + CAST(ISNULL(ic.increment_value, '1') AS CHAR(1)) + ')' ELSE '' END
        END + CHAR(13)
    FROM sys.columns c WITH (NOWAIT)
    JOIN sys.types tp WITH (NOWAIT) ON c.user_type_id = tp.user_type_id
    LEFT JOIN sys.computed_columns cc WITH (NOWAIT) ON c.[object_id] = cc.[object_id] AND c.column_id = cc.column_id
    LEFT JOIN sys.default_constraints dc WITH (NOWAIT) ON c.default_object_id != 0 AND c.[object_id] = dc.parent_object_id AND c.column_id = dc.parent_column_id
    LEFT JOIN sys.identity_columns ic WITH (NOWAIT) ON c.is_identity = 1 AND c.[object_id] = ic.[object_id] AND c.column_id = ic.column_id
    WHERE c.[object_id] = @object_id
    ORDER BY c.column_id
    FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, CHAR(9) + ' ')
    + ISNULL((SELECT CHAR(9) + ', CONSTRAINT [' + k.name + '] PRIMARY KEY (' +
                    (SELECT STUFF((
                         SELECT ', [' + c.name + '] ' + CASE WHEN ic.is_descending_key = 1 THEN 'DESC' ELSE 'ASC' END
                         FROM sys.index_columns ic WITH (NOWAIT)
                         JOIN sys.columns c WITH (NOWAIT) ON c.[object_id] = ic.[object_id] AND c.column_id = ic.column_id
                      WHERE ic.is_included_column = 0
                             AND ic.[object_id] = k.parent_object_id
                             AND ic.index_id = k.unique_index_id
                         FOR XML PATH(N''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, ''))
            + ')' + CHAR(13)
            FROM sys.key_constraints k WITH (NOWAIT)
            WHERE k.parent_object_id = @object_id
                AND k.[type] = 'PK'), '') + ')'  + CHAR(13)
    + ISNULL((SELECT (
        SELECT CHAR(13) +
             'ALTER TABLE ' + @object_name + ' WITH'
            + CASE WHEN fk.is_not_trusted = 1
                THEN ' NOCHECK'
                ELSE ' CHECK'
              END +
              ' ADD CONSTRAINT [' + fk.name  + '] FOREIGN KEY('
              + STUFF((
                SELECT ', [' + k.cname + ']'
                FROM fk_columns k
                WHERE k.constraint_object_id = fk.[object_id]
                FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, '')
               + ')' +
              ' REFERENCES [' + SCHEMA_NAME(ro.[schema_id]) + '].[' + ro.name + '] ('
              + STUFF((
                SELECT ', [' + k.rcname + ']'
                FROM fk_columns k
                WHERE k.constraint_object_id = fk.[object_id]
                FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, '')
               + ')'
            + CASE
                WHEN fk.delete_referential_action = 1 THEN ' ON DELETE CASCADE'
                WHEN fk.delete_referential_action = 2 THEN ' ON DELETE SET NULL'
                WHEN fk.delete_referential_action = 3 THEN ' ON DELETE SET DEFAULT'
                ELSE ''
              END
            + CASE
                WHEN fk.update_referential_action = 1 THEN ' ON UPDATE CASCADE'
                WHEN fk.update_referential_action = 2 THEN ' ON UPDATE SET NULL'
                WHEN fk.update_referential_action = 3 THEN ' ON UPDATE SET DEFAULT'
                ELSE ''
              END
            + CHAR(13) + 'ALTER TABLE ' + @object_name + ' CHECK CONSTRAINT [' + fk.name  + ']' + CHAR(13)
        FROM sys.foreign_keys fk WITH (NOWAIT)
        JOIN sys.objects ro WITH (NOWAIT) ON ro.[object_id] = fk.referenced_object_id
        WHERE fk.parent_object_id = @object_id
        FOR XML PATH(N''), TYPE).value('.', 'NVARCHAR(MAX)')), '')
    + ISNULL(((SELECT
         CHAR(13) + 'CREATE' + CASE WHEN i.is_unique = 1 THEN ' UNIQUE' ELSE '' END
                + ' NONCLUSTERED INDEX [' + i.name + '] ON ' + @object_name + ' (' +
                STUFF((
                SELECT ', [' + c.name + ']' + CASE WHEN c.is_descending_key = 1 THEN ' DESC' ELSE ' ASC' END
                FROM index_column c
                WHERE c.is_included_column = 0
                    AND c.index_id = i.index_id
                FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, '') + ')'
                + ISNULL(CHAR(13) + 'INCLUDE (' +
                    STUFF((
                    SELECT ', [' + c.name + ']'
                    FROM index_column c
                    WHERE c.is_included_column = 1
                        AND c.index_id = i.index_id
                    FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, '') + ')', '')  + CHAR(13)
        FROM sys.indexes i WITH (NOWAIT)
        WHERE i.[object_id] = @object_id
            AND i.is_primary_key = 0
            AND i.[type] = 2
        FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)')
    ), '')

PRINT @SQL
--EXEC sys.sp_executesql @SQL
END


SP_HELPTEXT 대안 3 MSSQL과 ORACLE

아우 내가 SP_HELPTEXT 때문에 몇번이나 수정버전 내놓는지 모른다.

아주 학을 땐다 학을 때.

SP_HELPTEXT 의 문제가 그리드 라인으로 화면에 뿌려주다 보니

아래의 화면처럼 가끔씩 정렬구조가 엉망으로 되어버린다.

이것 때문에 정렬 잘 맞추어 놓았다가 자꾸 깨져서 다시 맞추고 다시 맞추고를 한 100번은 한거 같다.

그러다가 생각해보니 라인으로 표시되면 그럴 이유가 없다는 글을 한번 본거 같다.

??

이런 간단한 방법이 있다니???

그래서 바꾼거를 결과물로 찍으니

메세지 결과물에 이렇게 아름답게 나오는 것이다.

씨붕 내가 대체 이때까지 뭐한거여?

자 결과물 올린다.


CREATE procedure sp_helptext2
@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(4000)

select @DefinedLength = 4000
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(4000) 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

CLOSE  ms_crs_syscom
DEALLOCATE  ms_crs_syscom

IF @Line is NOT NULL INSERT #CommentText VALUES( @LineId, @Line )

/* ------------------------------ SCRIPT 정리 시작 ------------------------------ */

/* 줄 끝 공백과 탭 제거 */
declare @seq int
declare @text nvarchar(4000)
declare @crlf nvarchar(2)

DECLARE ScriptCursor1 CURSOR LOCAL FORWARD_ONLY STATIC FOR
    select LineId, Text from #CommentText order by LineId

OPEN ScriptCursor1

FETCH NEXT FROM ScriptCursor1 INTO @seq, @text

WHILE @@FETCH_STATUS = 0 BEGIN
    IF @text LIKE '%' + CHAR(13) + CHAR(10) BEGIN
        SET @text = SUBSTRING(@text, 1, LEN(@text) - 2)
        SET @crlf = CHAR(13) + CHAR(10)
    END ELSE BEGIN
        SET @crlf = ''  
    END
    SET @text = REVERSE(@text)
    WHILE 1 = 1 BEGIN
        IF CHARINDEX(CHAR(9), @text) != 1 AND CHARINDEX(CHAR(32), @text) != 1 BREAK
        IF CHARINDEX(CHAR(9), @text) = 1 SET @text = SUBSTRING(@text, 2, 4000)
        IF CHARINDEX(CHAR(32), @text) = 1 SET @text = SUBSTRING(@text, 2, 4000)
    END
    SET @text = REVERSE(@text) + @crlf
    UPDATE #CommentText SET [Text] = @text WHERE LineId = @seq
    FETCH NEXT FROM ScriptCursor1 INTO @seq, @text
END

CLOSE ScriptCursor1
DEALLOCATE ScriptCursor1

/* SCRIPT 끝 케리지 리턴 제거 */
SET @seq = NULL
SET @text = NULL

DECLARE ScriptCursor2 CURSOR LOCAL FORWARD_ONLY STATIC FOR
    select LineId, Text from #CommentText order by LineId DESC

OPEN ScriptCursor2

FETCH NEXT FROM ScriptCursor2 INTO @seq, @text

WHILE @@FETCH_STATUS = 0 BEGIN
    IF @TEXT != CHAR(13) + CHAR(10) BREAK

    DELETE #CommentText WHERE LineId = @seq

    FETCH NEXT FROM ScriptCursor2 INTO @seq, @text
END

CLOSE ScriptCursor2
DEALLOCATE ScriptCursor2

/* SCRIPT 앞 케리지 리턴 제거 */
SET @seq = NULL
SET @text = NULL

DECLARE ScriptCursor3 CURSOR LOCAL FORWARD_ONLY STATIC FOR
    select LineId, Text from #CommentText order by LineId

OPEN ScriptCursor3

FETCH NEXT FROM ScriptCursor3 INTO @seq, @text

WHILE @@FETCH_STATUS = 0 BEGIN
    IF @TEXT != CHAR(13) + CHAR(10) BREAK

    DELETE #CommentText WHERE LineId = @seq

    FETCH NEXT FROM ScriptCursor3 INTO @seq, @text
END

CLOSE ScriptCursor3
DEALLOCATE ScriptCursor3

/* ------------------------------ SCRIPT 정리 끝 ------------------------------ */

/* SCRIPT PRINT */
SET @seq = NULL
SET @text = NULL

DECLARE ScriptCursor9 CURSOR LOCAL FORWARD_ONLY STATIC FOR
    select LineId, Text from #CommentText order by LineId

OPEN ScriptCursor9

FETCH NEXT FROM ScriptCursor9 INTO @seq, @text

WHILE @@FETCH_STATUS = 0 BEGIN
    PRINT @text

    FETCH NEXT FROM ScriptCursor9 INTO @seq, @text
END

CLOSE ScriptCursor9
DEALLOCATE ScriptCursor9

DROP TABLE  #CommentText

return (0) -- sp_helptext



환경변수 명령어처리(Setx Path)를 중심으로

원래 환경변수는 아래의 것을 명령프롬프트에서 넣으면 된다.

setx -m JAVA_HOME "d:/jdk"
setx path "%PATH%;%JAVA_HOME%\bin" /m
setx -m ORACLE_HOME "d:\OraClient"
setx -m NLS_LANG "KOREAN_KOREA.KO16MSWIN949"
setx -m TNS_ADMIN  "d:\OraClient"

setx path "%PATH%;%ORACLE_HOME%" /m


그런데 퍽킹 저장이 안되는 거다.

무슨일인데 안되지 하면서 계속 쳐다봤는데...

문자열이 잘린다는 소리였다.

씨붕 환경변수들 보면 mssql이 엄청나게 글자쓰고, 인텔이 엄청써서 보니깐 쓸수 있는 문자열이 1024로 짤리다니...

화딱지나서 

setx -m JAVA_HOME "d:/jdk"
setx /M PATH "%JAVA_HOME%\bin;%PATH%"
setx -m ORACLE_HOME "d:\OraClient"
setx -m NLS_LANG "KOREAN_KOREA.KO16MSWIN949"
setx -m TNS_ADMIN  "d:\OraClient"
setx path "%PATH%;%ORACLE_HOME%" /m

이걸로 바꾸어서 Path 설정했다.

이건 보니까 setX 라는 명령어가 1024 문자열 이상을 지원 안하는 버그(?) 때문이었다.
어쩔수 없이 다음에는 컴터 설치하자마자 패스부터 설정하고 나머지를 깔던지 해야겠다.


자바는 소중하니깐요.


스토어드 프로시저로 table create 명령줄 뽑아내기. MSSQL과 ORACLE

이 sp를 실행하면 테이블 구조의 내용을 script로 뽑아준다.
맨날 mssm의 수정 부분들어가서 script생성 어쩌구 눌러서 만들려면 귀찮다.


결과물은 아래 그림을 참조.



--◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆
--◆              (c) Copyright Brainnet Co..Ltd.  2005
--◆                   All rights reserved
--◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆
--◆ Procedure Name :  SP_Z_GET_TABLE_CREATE
--◆ Program Code   :  SP_Z_GET_TABLE_CREATE
--◆ Description    :  table create 명령줄 뽑아내기.
--◆ Author         :  홍길동
--◆ Date           :  2016. 06. 29.
--◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆
--◆ Modification Log
--◆
--◆ Date            In Charge    Description
--◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆
--◆ 2014. 12. 16.   softone     Initial Release
--◆
--◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆
CREATE PROCEDURE SP_Z_GET_TABLE_CREATE
(
      @P_TABLE_NAME                   nVarchar(100)
)
AS

BEGIN

    DECLARE @SQL TABLE(S VARCHAR(4000), ID INT IDENTITY)


    declare #ZSY_SYS_cur01 cursor for
      SELECT upper(name) o_name
        FROM sysobjects
       WHERE xtype = 'U'
       and name = @P_TABLE_NAME
       order by upper(name)
    OPEN #ZSY_SYS_cur01

    fetch next from #ZSY_SYS_cur01 into
                    @P_TABLE_NAME
    WHILE (@@fetch_status <> -1)
    BEGIN
        INSERT INTO  @SQL(S)
        SELECT 'CREATE TABLE ' + @P_TABLE_NAME + ' ('

        ;WITH AAA AS (
                SELECT OBJECT_NAME(o.parent_object_id) AS TABLE_NAME
                     , o.Name AS      CONSTRAINT_NAME
                     , cost_name.name COLUMN_NAME
                  FROM sys.objects o
                  JOIN sys.schemas s
                    ON o.schema_id = s.schema_id
                  JOIN sys.all_columns cost_name
                    ON o.object_id = cost_name.default_object_id
                   AND o.parent_object_id = cost_name.object_id
                 WHERE 1=1
                   AND o.type = 'D'
                   AND OBJECT_NAME(o.parent_object_id) = @P_TABLE_NAME

        )
        INSERT INTO @SQL(S)
        SELECT CASE WHEN ORDINAL_POSITION = 1 THEN '   ' ELSE ' , ' END
             + A.COLUMN_NAME
             + N' ' + DATA_TYPE +
                                  CASE WHEN CHARACTER_MAXIMUM_LENGTH > 0 THEN '(' + CONVERT(VARCHAR(MAX), CHARACTER_MAXIMUM_LENGTH) + ')'
                                       WHEN NUMERIC_PRECISION > 0 THEN '(' + CONVERT(VARCHAR(MAX), NUMERIC_PRECISION)+ ',' + CONVERT(VARCHAR(MAX), NUMERIC_SCALE) + ')'
                                       WHEN DATETIME_PRECISION > 0 THEN ''
                                  END
             + N' ' + ( CASE WHEN IS_NULLABLE = 'NO' THEN 'NOT ' ELSE '' END ) + 'NULL '
             + N' CONSTRAINT ' + CASE WHEN CONSTRAINT_NAME IS NULL THEN '' ELSE CONSTRAINT_NAME END
             + N' ' + CASE WHEN COLUMN_DEFAULT IS NULL THEN '' ELSE COALESCE('DEFAULT '+COLUMN_DEFAULT,'') END


          FROM INFORMATION_SCHEMA.COLUMNS A
          LEFT
          JOIN AAA B
            ON A.TABLE_NAME  = B.TABLE_NAME
           AND A.COLUMN_NAME = B.COLUMN_NAME
         WHERE A.TABLE_NAME  = @P_TABLE_NAME
         ORDER
            BY A.ORDINAL_POSITION
         ;
        INSERT INTO  @SQL(S)
        SELECT ' )'

        INSERT INTO  @SQL(S)
        SELECT ' ALTER TABLE ' + @P_TABLE_NAME + ' ADD CONSTRAINT ' + ' PK_' + @P_TABLE_NAME + N' PRIMARY KEY ' 
        ;WITH AAA AS (
                SELECT OBJECT_NAME(o.parent_object_id) AS TABLE_NAME
                     , o.Name AS      CONSTRAINT_NAME
                     , cost_name.name COLUMN_NAME
                  FROM sys.objects o
                  JOIN sys.schemas s
                    ON o.schema_id = s.schema_id
                  JOIN sys.all_columns cost_name
                    ON o.object_id = cost_name.default_object_id
                   AND o.parent_object_id = cost_name.object_id
                 WHERE 1=1
                   AND o.type = 'D'
                   AND OBJECT_NAME(o.parent_object_id) = @P_TABLE_NAME

        )
        INSERT INTO  @SQL(S)
         SELECT  CASE WHEN A.column_id = 1 THEN ' ( ' ELSE ' , ' END + INDEX_COL(@P_TABLE_NAME, A.INDEX_ID, A.INDEX_COLUMN_ID ) COL_NM
           FROM  sys.index_columns A
           JOIN  SYSINDEXES B
             ON  A.object_id = B.ID
            AND  B.INDID = A.INDEX_ID
          WHERE  A.object_id = OBJECT_ID( @P_TABLE_NAME )

        INSERT INTO  @SQL(S)
        SELECT ' )'
    fetch next from #ZSY_SYS_cur01 into
                    @P_TABLE_NAME
    END


    CLOSE #ZSY_SYS_cur01
    DEALLOCATE #ZSY_SYS_cur01

    SELECT * FROM @SQL

END

cross apply 셈플 MSSQL과 ORACLE

select * 
  from oqm_qc_category A
 where start_dt in ( select MAX(x.start_dt)
                       from oqm_qc_category x
                      where A.qc_category_cd = x.qc_category_cd )
   --and qc_category_cd = 'M170604542'

SELECT TA.*
FROM oqm_qc_category TA
   CROSS APPLY (SELECT TOP 1 * FROM oqm_qc_category TB
                             WHERE TB.qc_category_cd = TA.qc_category_cd
                              AND TB.start_dt <= TA.start_dt
                              ORDER BY start_dt DESC) TT
--where    TA.qc_category_cd = 'M170604542'


자바 및 오라클 환경설정 한방에 처리하기 MSSQL과 ORACLE

우선 오라클이랑 자바를 환경변수에 일일이 넣고 싶지 않으신 분들을 위하여 이 글을 바친다.


필자의 경우 오라클클라이언트랑 자바클라이언트를 항상 D드라이브에 설치한다.
왜냐면 다시 설치하기가 귀찮기 때문이다.


그래서 포멧하면 다시 환경설정 들어가서 Path치는 것이 너무나 싫다.

즉, 이거 타이핑하기가 귀찮다는 소리.


오라클 클라이언트 설치없이 쓰는 방법은 내 블로그 찾아보면 나올 것이다.
그걸 전제로 이야기를 풀어본다.

환경변수에 들어가서 일일이 클릭하고 치기가 귀찮으시면 cmd창 열어서

아래의 것을 치면 완성됨


setx -m JAVA_HOME "d:/jdk"
setx path "%PATH%;%JAVA_HOME%\bin" /m
setx -m ORACLE_HOME "d:\OraClient"
setx -m NLS_LANG "KOREAN_KOREA.KO16MSWIN949"
setx -m TNS_ADMIN  "d:\OraClient"

setx path "%PATH%;%ORACLE_HOME%" /m

폴더명칭이나 드라이브 명칭만 바꾸면 됩니다.


분산 트렌잭션 DTC, RPC 가 안되는 분들을 위한 트러블슈팅 (Windows Server 2012버전 중심으로) MSSQL과 ORACLE

젝일! 

최근 MS-SQL 두대를 링크드서버(linked-server) 를 통하여 연결한 후
분산트렌젝션을 했다.

그런데 조까튼 문제가 발생했다.

한놈은 Windows Server 2003 이고 
한놈은 Windows Server 2012 였다.


문제는 이 더러븐 놈의 셋팅이 예전에 할때는 잘 되었는데 이번에는 죽어도 안되는 거였다.

즉 서버 2003에서 이런식으로 작성해서 저장하면 




보안구성

요런식으로 넣으면 레지스트리의 
HKLM\SOFTWARE\Microsoft\Rpc\internet 부분에 저장이 된다. (아래화면 참조)

즉, 이 부분을 레지스트리에 넣으나, 프로그램으로 넣으나 같은 결과물을 가진다는 말이다.



그런데, Fucking 2013 서버는 
전혀 다른 메카니즘을 보이고 있었다는 것을 간과했다.


나는 예전에만 분산트렌젝션을 일으켰기 때문에 기억은 2003 서버 기준으로만 생각하고 있었다.

그런데,

일단 화면 부터 퍼킹 헬이다.


포트번호 넣고 MSDTC설정 해볼까? 했는데 

MSDTC가 여기에 없다.
즉, 여기에 있다.




보다 시피 옵션도 존나리 많다.

하지만, 이건 넘어가리라고 생각했다.

근데 Dtcping을 통하여 통신이 일어나지 않았다.

어떤 문서 보니깐 HKLM\SOFTWARE\Microsoft\Rpc 여기에다가 포트 넣으라고 되어있어서
씨붕 넣었다.

안되었다.

다시 internet 폴더에 



넣었다.


이게 무슨 개 삽질일까?


아마 인터넷폴더를 번역하면서 어떤 ㅂㅅ이 internet을 폴더라고 생각하지 않고 RPC폴더에 바로 넣는 것으로 착각했나 보다.



암튼 개삽질이었음.



정리해보자

1. RPC통신을 하려면 두 MSSQL 컴퓨터간에 컴퓨터이름으로 ping을 할수가 있어야 한다.

즉 CMD창(명령프롬프트)에서 ping xxx.xxx.xxx.xxx 가 아닌 A서버의 명칭 
 - 서버명칭은 제어판->시스템 에서 보면 나옵니다. - 

  즉, ping rpc서버1[가칭] 과 ping rpc서버2[가칭] 가 다 먹혀야 한다.
     이게 안먹힌다면, windows\system32\drivers\etc\hosts파일을 열어서 
     xxx.xxx.xxx.xxx  rpc서버1 을 추가하면 됩니다.
서버 재부팅 해주세요.
  
   이렇게 했는데도 안먹히면 분명히 firewall이 막혀있습니다.  
   네트웍 관리자에게 Ping 막혀있는지 물어보세요

2. RPC포트 열려있어야 합니다. 
   135번 포트입니다.
  이게 내부방화벽으로 막혀있을 수도 있고, 


아니면 네트웍 방화벽에도 막혀있을 수 있으니 네트웍 관리자에게 물어보세요


3. RCP가 내부적으로 사용하는 동적포트를 뚫어주어야 합니다.


그건 위에 다 설명되어 있습니다.




이후 DTCping.exe파일을 두 서버에서 동시에 실행한 후에


두 포트가 정상적으로 오는지 보고 통신이 왔다갔다 하는지를 보세요

한군데서 실행한 후에 다른데서 실행하면 두놈다 반응을 일으킵니다.
A서버에서 실행한 후 컴터이름을 치고 Ping을 했는데, B서버에서 반응이 없으면 RPC가 안되는 겁니다.


이게 되면 분산트렌잭션은 거의 100% 실행됩니다.

참조

http://nagid.egloos.com/2986380


오라클에서 MSSQL처럼 TOP 1 을 통하여 UPDATE하기

우선 http://nagid.egloos.com/3017597 이 게시물 참조.


SET SERVEROUTPUT ON;
BEGIN
                MERGE INTO hrap002 m 
                USING (SELECT rid, ROWNUM rn FROM (SELECT ROWID rid FROM hrap002
                                                    where emp_id = '10001'
                                                   ORDER BY appnt_dt desc, SEQ_NO desc)
                                            where ROWNUM = 1       
                                                   ) s 
                ON (m.ROWID = s.rid) 
                WHEN MATCHED THEN 
                UPDATE SET job_title_cd =  '11'
                
                ;   
          
    DBMS_OUTPUT.PUT_LINE( TO_CHAR(SQL%ROWCOUNT) || ' 줄 반영되었어..');
    DBMS_OUTPUT.PUT_LINE( TO_CHAR(etl.get_merge_insert_count) || ' 줄 추가되었어.');
    DBMS_OUTPUT.PUT_LINE( TO_CHAR(etl.get_merge_update_count( SQL%ROWCOUNT ))|| ' 줄 수정되셨어.');
                
END;

요런 방식으로 쓰면 자기가 원하는 방식으로 업데이트를 칠수 있음.
물론 이 방식으로 Insert도 할 수 있음.

최근에 고전 Xcom1 로 OpenXcom 을 해보았다. 게임?

1. OpenXcom은 두가지 버전 모두를 지원하니 이쪽도 해보고 저쪽도 해봐서 좋다.

일단 화면 투척



그지같은 외계인 비행접시 2대나 걸린 스크린샷이다.

이놈들 초반에 너무 강해서 보이자마자 몇방맞고 탱크 빈사상태다.

물론 이판은 내가 보이자마자 후퇴한 미션이다.


암튼 xcom1도 무지막지한 보정을 통해서 예전에 쉽게 끝내신분들도 한번 해보면 힘들거라고 생각한다.


물론 본인은 SuperHuman 에다가 철인모드(ironman - 저장은 자동으로되고 이전버전으로 로딩안됨. )


끝내기는 했다.


오랫만에 한거라서 초반에 태크트리 좀 꼬여서 실패(2번이나... 헉) 를 하기도 했지만 무난하게 끝낸거 같다.

간만에 불태웠음.


어라? 이미지들이 왜 올리면 다 짤리지?


최근에 고전 Xcom2 인 TFTD의 OpenXcom 을 해보았다. 게임?




일단 화면을 한번 보자

1. 일단 전체 해상도가 그래픽카드 지원되는 것 까지 다 지원한다.
   이 말은 즉, 예전에 갑갑한 정도의 화면이 보여줘서 스크롤이 존나 많이 발생했는데 이번 버전은 그래픽카드 지원까지로 크게 볼수있다. 덕분에 그래픽이 깔끔한 것 같은 느낌이 든다.
2. 난이도가 일부 변경되었다.
   본인은 원래 Xcom1은 시시하고 Xcom2는 초인난이도 즉, "Super Human" 이 아니면 안한다.
   그런데, 이번에 그냥 간단하게 생각하고 Super Human으로 했는데 개박살 났다. 그것도 2번이나.

   왜 그런고 하니, 처음에 원래 기술개발이 진행되지 않으면 3개월이내에는 기지로 처들어오지 않았다.
   그런데 이놈들 2개월 되니깐 처들어 온다.
   어떤때는 1개월에 처들어 올때도 있었다.
   아쿠아로이드인 초록색 최고 쉬운 놈 (섹토노이드 같은 놈)들만 처들어 올때는 상관 없는데,
   문제는 잠수복입은 놈과 같이 처들어오면 초반 공격형 무기가 낮을때는 죽일 수가 없다는 점이다.

   3방 4방 맞추면 죽일수 있을 것 같았지만, 데이지가 들쑥날쑥이라서 공격력이 너무 낮으면 공격차체가 무위로 돌아가는 시스템인거 같은데, 문제는 고폭수류탄을 3~4방 터뜨려도 멀쩡하다는 점이다. 물론 다른 것들의 무기도 마찬가지임.

최소한 "Sonic purser" 정도의 외계인 수류탄이나, 외계인무기 정도는 되야 안정적으로 딜을 할수 있는 관계로 기지침공미션에서 전멸했다. 탱크를 많이 모았어도 탱크로 부술수 없었다.
그리고 또한 데미지 보정이 많이 일어나서 예전에는 탱크만 있어도 초반미션은 어느정도 해결되었는데, 이번 버전은 탱크신공으로는 깨기가 불가능한 상황이 벌어졌다. 

암튼 그래서 초반에는 존나 힘들었다.

아~ 그리고 이놈들 이제 문도 잘따고 들어온다. 물론 엄청난 인공지능은 아니지만
적이 우리편 우주선 문을 따고 유도미사일로 우리편 전멸시키는 장면을 내가 목격했다. 와우~

암튼 이래저래 세이브를 통해서 마지막 미션만 남겨놓은 상태.


3. 여러가지 옵션을 통해 인터페이스가 엄청난 개선이 일어났다.
   이건 해보면 알겠네요.



암튼 옛날에 해보신 분들이라면 꼭 해보시고,
최근 버전의 Xcom 시리즈를 즐겨하셨던 분들이시라면 마음 단단히 먹고 해보세요.


SP_HELPTEXT 의 대안 -> 이건 정말 미칠 일이다. MSSQL과 ORACLE

MSSQL의 sp_helptext 는 정말 유용한 기능을 제공하는 SP 이다.

하지만 문제는 이놈이 문자열의 크기가 256자리가 넘어가면 강제로 개행문자를 넣어주는 어처구니가 없는 버그가 있다.


예)

DECLARE @SQL NVARCHAR(MAX);
SET @SQL = 'CREATE PROCEDURE sp_Test_sp_helptext AS SELECT '''
+ REPLICATE('X',280)
+ ''' as [Stored Procedure Select Result];';
EXEC (@SQL);
GO

이렇게 SP 명칭 sp_Test_sp_helptext에 280자리 정도의 X가 들어간 SP를 실행해본다.


보이는 가?

칸이 지멋대로 2줄로 나왔다.

정상적으로 나왔다면



이건 아래와 같이 붙어서 
나와야 한다.


그래서 내가 화딱지 나서 구글신에게 물어서 알아봤다.
그 결과물이 nagid.egloos.com/3024869 이다



그런데, Fucking Asshole !!!!!





왜 모든 개행문자가 다 붙어버리냐?

아우 빡쳐!



테스트한 위한 예시


ALTER PROCEDURE sp_Test_sp_helptext AS SELECT 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' as [Stored Procedure Select Result]

print 'fadsfasd'



print N'요로코롬 개행이 좀 보여야지'
;


이걸 
EXEC sp_helptext2 sp_Test_sp_helptext  
로 실행하면


CREATE PROCEDURE sp_Test_sp_helptext AS SELECT 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' as [Stored Procedure Select Result]
print 'fadsfasd'
print N'요로코롬 개행이 좀 보여야지'
;

이래 나온다.


이걸 어따써?


해서 또 다시 구글링 했다.

그래서 완전판은 아니지만
1행에 4000자 정도까지는 버텨줄 수 있는 SP를 구했다.

4000를 넘기면 어떻게 하냐구요?  쓰지마세요. 그렇게 만들지 마세요.
가독성 제로입니다. 그렇게 만든 놈은 때리세요.

그러면 새로운 버전을 내놓겠습니다.

CREATE PROCEDURE [dbo].[sp_helptext2] (@ProcName NVARCHAR(256))
AS
BEGIN
  DECLARE @PROC_TABLE TABLE (X1  NVARCHAR(MAX))

  DECLARE @Proc NVARCHAR(MAX)
  DECLARE @Procedure NVARCHAR(MAX)
  DECLARE @ProcLines TABLE (PLID INT IDENTITY(1,1), Line NVARCHAR(MAX))

  SELECT @Procedure = 'SELECT DEFINITION FROM '+db_name()+'.SYS.SQL_MODULES WHERE OBJECT_ID = OBJECT_ID('''+@ProcName+''')'

  insert into @PROC_TABLE (X1)
        exec  (@Procedure)

  SELECT @Proc=X1 from @PROC_TABLE

  WHILE CHARINDEX(CHAR(13)+CHAR(10),@Proc) > 0
  BEGIN
        INSERT @ProcLines
        SELECT LEFT(@Proc,CHARINDEX(CHAR(13)+CHAR(10),@Proc)-1)
        SELECT @Proc = SUBSTRING(@Proc,CHARINDEX(CHAR(13)+CHAR(10),@Proc)+2,LEN(@Proc))
  END
  --* inserts last line
  insert @ProcLines 
  select @Proc ;

  SELECT Line FROM @ProcLines ORDER BY PLID
END
GO


이 버전은 라인이 지원하는 한계까지 나옵니다.
개행 함부로 나오지 않아요.


쓸만합니다.







오늘날 개신교도의 문제점. 후덜덜

제목은 거창하지만 내용은 간단하다.

예수님의 말씀은 따르지 않아서 이다.

예수님이 뭐라고 하셨나?

진리를 알지니 진리가 너희를 자유케 하리라(요 8:32)


진리를 알라고 설파하신다.
혹자는 진리가 예수니 예수님을 알면 자유로워진다는 얼토당토 않는 말을 하는데, 아휴 말귀를 좀 알아 처먹어라.

예수님 = 진리
라면 진리를 알라고(능동) 하지 않고 믿어라(수동) 라고 말해야 한다.

예수님이 말씀하신 것은 믿지말고 알아라는 거다.


끊임없이 물음을 가지고 알려고 노력하라는 점에서 
예수님은 진리를 추구하여 자유로워지라는 말을 한거다.


근데 오늘날 신앙인이라고 하는 개신교도들은 어떤가?

무조건 "아멘"만을 외친다.

신이 머리를 줬는데 머리는 어디다 팔아먹고 뇌없는 믿음만 보여주고 있다.

머리를 안쓰고 진리를 추구하지 못하면 자유롭지 못하다. 
즉, 노예가 된다는 말이다.
노예로 살지마라고 예수님 께서 말씀하셨는데, 굳이 노예로 살겠다는 사람들이 너무 많다.


종교개혁 이후에 성경은 누구나 글만 깨우치면 읽을 수 있다.

존나 어려운 라틴어가 아니고, 영어, 한국어로 글을 읽을 수 있다는 말은
누구나 성경을 읽고 능동적으로 해석하고 그 가르침을 따르면
예배당에 안다녀도 영생을 얻는다는 말이다.


목사는 그저 성경을 읽어주고 해석해주는 직업이다. 목사를 신으로 착각하는 사람들이 너무 많다.
그래서 사이비가 나오는 거다.
목사는 목자가 아니다.

목자는 오직 예수님 밖에 없다.
즉, 성경의 해석을 다르게 설교하는 목사놈이 있다면 "아멘"이라고 하면 안되고 "미친놈" 하고 외쳐야 하는 것이다.

신을 핑계로 나쁜 짓을 한다면 진리추구자의 입장에서 능동적으로 반박하고 반대해야 한다.



그런데 오늘날의 개신교도들은 어떤가?

나는 가만히 보니, 이들은 뇌를 어디다 누고 온 것 같다.
믿음만 강요하는 사람을 원한다면 신은 뇌를 주지 않았을 것이다.
근데 그 뇌를 하찮게 이용하는 개신교인을 보면 
이것들이 신을 능욕하는 게 아닌가 싶다.





추억의 게임 xcom-2 을 superhuman 모드로 최단시간 돌파 ( 실전 1) 게임?

드디어 xcom2를 구했다.

윈도7에서 도스박스로 되어있는 버전인데 스크릿 샷을 찍을 수 있음을 확인했다.

고로 이제 포스팅만 하면 된다.


주말에 달려서 초인모드로 5일정도만에 끝내는 것을 목표로 진행해 보겠다.

요즘 체력이 안되서 게임이라는 것도 오래 못하는 단점이 있는 고로 5일만에 외계인들 섬멸하는 것이 목표이다.

하지만 너무 쉬우므로 제한을 두기로 했다.


제한요건
1. SAVE & LOAD 신공은 없는 것으로 한다.
   저장질로 하면 너무 쉬우므로 저장질은 없는 편이 더 낫다는 것이 나의 결론이다. 이걸 쓰면 아무나 깬다.

2. 쉴 때 저장하는 것은 필요하므로 저장질은 단 1번만 하기로 한다. 이것도 쉬기 위한 저장이다.
   전투에 패배해서 뒤로 가는 것은 없다.
   물론 여러번 저장해놓고 꼼수로 1번 저장한 것처럼 보여준다면 거짓으로 돌파할 수 있겠지만,
   그런 시시껄렁한 것으로 포스팅을 더럽히고 싶지 않다.

3. 게임의 버그로 인하여 진행이 안 될때는 중단시점의 로드를 허용한다.
   간혹 있다. 뻣어버려서 도저히 진행이 안될때 그럴때는 별수 있나? 로드해야지.

4. 하루에 한번 이상은 저장 않기로 한다.
   즉, 버그로 맛탱이가면 어제 꺼로 다시 작업해야 한다는 말임.


그럼 포스팅 시작하겠다.

근데 오늘은 맛뵈기만...



추억의 게임 xcom-2 을 superhuman 모드로 최단시간 돌파하기(part 5) 게임?

귀찮음을 무릅쓰고 시리즈의 마지막 끝을 내기 위해 계속 씁니다.


외계인 기지를 찾으러 내렸을 때, 화면의 기준으로 우측에 기지입구가 있는 지역에 내릴수가 있다. 4분의 1 가능성
여기가 명당 자리다.

여기에 내리기 위해 몇번 왔다 갔다 하는 게 좋다.
왜냐면 외계인 


tasoth leader ( tasoth 의 지도자)가 정신조종 스킬을 가지고 있기 때문이다.
이놈을 생포해야 하는데, 생포방법은 별거 없음.
초반에는 쇼크를 때릴수 있는 무기가 없기 때문에 stun load 로 지지는 수 밖에 없는데
문제는 초반에는 이놈을이 병사들을 정신조종을 하기 때문에 여간 힘든게 아니다.

그래서 초반에 탱크 2대로 입구를 막고 병사 2명을 무장해제 시킨다면 적본거지에 투입하면
정신력의 수치를 알수 있습니다.

정신력 저항이 약한 놈은 보이지도 않는 거리에서 걸려서 적의 편이 됨.
한마디로 미침.
이런 놈은 필히 버려야 함.
근데 대부분 이런 놈은 대위급 쯤 되는 놈이 대부분임.

어쨌거나 루키라도 좋으니 정신력이 좀 견디는 2명을 데리고 가서
반드시, 탱크로만 주변을 조금 정리해주어야 함.

딱 2~3번만 왔다갔다 하면 표가 남.
초반에 웅웅 거리면서 멀리서 정신조정 하려고 하는데 하자마자 패닉이나, 정신조정 당한다면 담에는 이놈은 안싣고 와야함.

3~4번 견디는 놈이 있다면 이놈은 주위만 좀 정리해주면 납치를 할 수 있는 종자가 됨.


그럼 천천히 주위를 하나씩 정리하고 문을 열고 들어간 후, 2층을 진압해야 함.

물론 이건 탱크가 먼저 몇대 때려야 함.
탱크가 몸빵이 안되서 부숴지기도 하지만, 다 부서지고 1놈만 납치해도 이 최단깨기 미션은 성공하는 거임.

일단 스턴이 성공하면, 저같은 경우 조건에 맞는 병사만 있다면 90%의 확률로 납치함.

과학자를 투입해서 MC Disruptor! 만 만들면 게임 끝.

계속 마인드 컨트롤로 연습하면 안걸려드는 게 없음.


자~ 정리하자

초반에 에어리언 납치를 잘해야 함. Deep one 은 납치와 시체 둘다 유용하므로 첫번째 항구 미션에서 반드시 생포
모든 쓸모없는 장비는 다 팔아버리고 그 돈으로 과학자를 타이트하게 산다.

연구를 한다. 

배 납치미션은 지루하므로 1마리만 죽이고 도망오면 된다.
끝내기는 어렵지만 그보다 맵이 너무 커 수색이 짜증나므로 나는 절~대 이 미션은 안한다.

wide 레이더로 탐사하거나 전투기를 일부러 북극쪽에 패트롤 시켜보면 외계인 기지 하나 쯤 나온다.
거기서 출격/후퇴를 반복하면서 정신력 강한 병사2명과 탱2두대로 반드시 tasoth leader 를 생포하자.

이쯤이 약 겜 시간으로 3개월 쯤 된다.

실제 미션은 1개월당 3개정도 미션이 있다고 가정하면 끽해야 9개 미션으로 tasoth leader 를 생포하는 셈이다.
물론 기지 출격/후퇴를 반복은 제외. 어차피 후퇴했다가 기름만 채우고 바로 다시 투입되는 것이다.

여기까지 하면 마인드컨트롤 훈련시설 까지 만들게 될거고
그 이후 마인드 컨트롤 훈련을 1달 시키면 6개월이나 그 이전에 마인드컨트롤을 하는 병사가 완성된다.


물론 초반에는 마인드컨트롤 디게 못한다.
이게 무슨 소용이 있을지 모르겠다고 생각들어도 계속하면 숙련도가 높아진다.
어느정도 높아지면 그때부터는 돈이 남아돌게 된다.
여전히 숙소와 연구소와 과학자를 충분히 확보하고 살아있는 에어리언이 있다면 팔아치우고 기지로 간다.

기지에서 힘들어도 반드시 lobsterman navigator ( 가재 운항사)와 obsterman commander 를 꼭 기절시켜서 운반 혹은 미션을 끝내자

그럼 이제 끝난거다.

기술개발 빡시게 하면 그 다음은 최종비행 유닛을 만들수 있고 외계인 본거지에 출동할 수있게 된다.

이 일련의 작업이 컴퓨터의 시간으로 12개월안에 끝낼수 있다.
미션수로 따지면 30개 미션 정도만 하면 돌파할 수 있고,
정말 귀찮다면 필요 없는 미션 넘기고 술렁술렁하면 30개 이내의 미션으로도 돌파할 수 있다.



문제는 그거다.

1. 최단 컴퓨터 개월수 를 목표로 할 것인가? -> 이걸 원하면 미션은 거의 다 수행해야 한다. 그것도 good 이상으로.
그래야 돈이 많이 들어와서 과학자 많이 뽑고 빨리 끝낸다.


2. 최단 플레이 시간을 목표로 할 것인가? -> 이걸 원하면 배납치 미션은 넘어가고 왠만큼 짜증나는 외계인 기지 침략 미션은 다 안하고 외계인 최종시설만 폭파하고  lobsterman navigator ( 가재 운항사)와 obsterman commander 를 꼭 기절시켜서 데려오면 된다.



나는 플레이가 귀찮으므로 2번 루트를 꼭 탄다.

왜냐면 싸우는 것보다 찾는게 더 지겹다.
꼭꼭 숨어있는 놈들은 제일 짱나기 때문이다. 안나온다. 쩝


이거 동영상을 찍을 수 있으면 내가 찍어서 올려보고 싶은데... 








추억의 게임 xcom-2 을 superhuman 모드로 최단시간 돌파하기(part 4) 게임?

존나 오랜 시간 이후에 글을 올려본다.

나의 게으름은 상상을 초월하므로 이거 만들어 올리기 정말 힘들어서 안했다. 내가 백수도 아니고..

초인모드 즉, SUPERHUMAN 은 초반에만 잘 하면 최단기간에 끝낼 수 있다.

즉, 외계인 수용시설을 제일 처음 짓고 항구미션까지 무손실로 버텨야 한다.
무손실로 버티는 요령은 당연히 탱크이고 탱크는 내구력이 짱이지만 초반에 명중률은 쥐약이다.

첨에는 탱크로 정찰하고 수류탄으로 죽이고, 섹토이드 조차도 1방에 안죽는 초인모드라 2방 쏴야 한다.

초반에  Coelacanth Gas Cannon 이라는 42달러짜리 3개와 Solid Harpoon Bolts라는 총알 90개
짜리를 사야하는데 이걸 사기 위해서 창고에 있는 것은 모조리 팔자.
단, 전투기에 들어가는 하푼은 팔면 안되고 최소한의 무기는 있어야 하니 일반폭탄(general 폭탄)은 팔지말고 바행기에 둬야 함.

그리고 약간의 메디컬 플레어 (야간 반짝이) 몇개는 사야한다. 
밤에 시야가 극악으로 줄어들기 때문에 몇개 던지고 나중에 그 자리에 가서 줍고 또 던지고를 반복한다.

초반 탱크 2대로 적들을 털고 가능한한 모든 자원을 털어 과학자를 사서 연구를 하면 
항구미션이 만들어지고 항구에서 Deep One 을 생포해야 한다. 이놈 생포 못하면 연구테크 꼬임.

생포하는 방법은 역시 탱크가 앞에서 몸빵하면 됩니다. 그후 stun load 인가로 생포하면 됨.
deep one을 연구하면 아쿠아플라스틱을 연구하게 되고 이후 테크는 비행유닛 테크만 잘타면 날아다니면서 끝낼수 있습니다.
그때되면 쉬워짐.

최단시간에 돌파에 가장 중요한거, 돈이 좀 모이면 무조건 레이다 설치해서 외계인 기지를 찾으면 만사해결됨.
<- 이게 가장 중요.

외계인 기지를 찾으면 탱크2대, 무기하나도 없는 병사를 끌고 외계인 기지에 무조건 갑니다.
가서 보면 정신능력이 개판인 애들은 가자마자 적에게 마음을 빼앗깁니다.


그럼 그놈은 버려야 할 놈입니다.
몇번 왔다갔다 하면서 정신감응에 잘 안 걸리는 놈을 찾습니다.


 




[MS-SQL]에서 거래처별 품목, 단가에 대한 적용일을 시작~종료일로 정렬하기 MSSQL과 ORACLE

WITH HRAP_SEQ AS 
(
    SELECT ROW_NUMBER() OVER(ORDER BY ITEM_ID, VEND_CD, START_DT DESC) SEQ_NO
         , A.ITEM_ID
         , A.VEND_CD
         , A.PRICE
         , A.START_DT
      FROM SSC_SALE_PRICE A
     WHERE A.USE_FLAG = '1'
       AND A.PRICE_APPROVAL_FLAG = '1'
)
SELECT A.ITEM_ID
     , A.VEND_CD
     , A.PRICE
     , A.START_DT
     , CONVERT(VARCHAR(8), DATEADD(DAY, -1, CONVERT(DATETIME, ISNULL(B.START_DT, '29991231'), 112)), 112)  END_DT
  FROM HRAP_SEQ A
  LEFT
  JOIN HRAP_SEQ B
    ON A.ITEM_ID  = B.ITEM_ID
   AND A.VEND_CD  = B.VEND_CD
   AND A.SEQ_NO   = B.SEQ_NO + 1
 ORDER
    BY A.ITEM_ID
     , A.VEND_CD
     , A.START_DT DESC
     , A.SEQ_NO   DESC

[MS-SQL]에서 거래처별 품목, 단가에 대한 적용일을 시작~종료일로 정렬하기기

WITH HRAP_SEQ AS 
(
    SELECT ROW_NUMBER() OVER(ORDER BY ITEM_ID, VEND_CD, START_DT DESC) SEQ_NO
         , A.ITEM_ID
         , A.VEND_CD
         , A.PRICE
         , A.START_DT
      FROM SSC_SALE_PRICE A
     WHERE A.USE_FLAG = '1'
       AND A.PRICE_APPROVAL_FLAG = '1'
)
SELECT A.ITEM_ID
     , A.VEND_CD
     , A.PRICE
     , A.START_DT
     , CONVERT(VARCHAR(8), DATEADD(DAY, -1, CONVERT(DATETIME, ISNULL(B.START_DT, '29991231'), 112)), 112) END_DT
  FROM HRAP_SEQ A
  LEFT
  JOIN HRAP_SEQ B
    ON A.ITEM_ID  = B.ITEM_ID
   AND A.VEND_CD  = B.VEND_CD
   AND A.SEQ_NO   = B.SEQ_NO + 1
 ORDER
    BY A.ITEM_ID
     , A.VEND_CD
     , A.START_DT DESC
     , A.SEQ_NO   DESC

[ORACLE]에서 거래처별 품목, 단가에 대한 적용일을 시작~종료일로 정렬하기 MSSQL과 ORACLE

WITH HRAP_SEQ AS 
(
    SELECT ROW_NUMBER() OVER(ORDER BY ITEM_ID, VEND_CD, START_DT DESC) SEQ_NO
         , A.ITEM_ID
         , A.VEND_CD
         , A.PRICE
         , A.START_DT
      FROM SSC_SALE_PRICE A
     WHERE A.USE_FLAG = '1'
       AND A.PRICE_APPROVAL_FLAG = '1'
)
SELECT A.ITEM_ID
     , A.VEND_CD
     , A.PRICE
     , A.START_DT
     , TO_CHAR(TO_DATE(NVL(A.START_DT, '29991231'), 'YYYYMMDD') - 1, 'YYYYMMDD') END_DT
  FROM HRAP_SEQ A
  LEFT
  JOIN HRAP_SEQ B
    ON A.ITEM_ID  = B.ITEM_ID
   AND A.VEND_CD  = B.VEND_CD
   AND A.SEQ_NO   = B.SEQ_NO + 1
 ORDER
    BY A.ITEM_ID
     , A.VEND_CD
     , A.START_DT DESC
     , A.SEQ_NO   DESC

[MS-SQL]에서 거래처별 품목, 단가에 대한 적용일을 시작~종료일로 정렬하기기

WITH HRAP_SEQ AS 
(
    SELECT ROW_NUMBER() OVER(ORDER BY ITEM_ID, VEND_CD, START_DT DESC) SEQ_NO
         , A.ITEM_ID
         , A.VEND_CD
         , A.PRICE
         , A.START_DT
      FROM SSC_SALE_PRICE A
     WHERE A.USE_FLAG = '1'
       AND A.PRICE_APPROVAL_FLAG = '1'
)
SELECT A.ITEM_ID
     , A.VEND_CD
     , A.PRICE
     , A.START_DT
     , CONVERT(VARCHAR(8), DATEADD(DAY, -1, CONVERT(DATETIME, ISNULL(B.START_DT, '29991231'), 112)), 112) END_DT
  FROM HRAP_SEQ A
  LEFT
  JOIN HRAP_SEQ B
    ON A.ITEM_ID  = B.ITEM_ID
   AND A.VEND_CD  = B.VEND_CD
   AND A.SEQ_NO   = B.SEQ_NO + 1
 ORDER
    BY A.ITEM_ID
     , A.VEND_CD
     , A.START_DT DESC
     , A.SEQ_NO   DESC


[MS-SQL] 속도 향상을 위한 테이블 분할에 대한 고찰(조회에 대한 고찰)(3) MSSQL과 ORACLE

그냥 데이터를 가지고 하니 체감이 좀 덜해서 예전에 쓰던 사이트의 DB로 테이블 분할에 대한 속도 향상을 체감해 보겠다.


OMM_OUT_HIST -> 출고를 담당하는 테이블인데 갯수가 3606539개이다.

대략 3백6십만건 쯤 된다고 생각하시면 되겠다.

들어가 있는 칼럼은 61개 짜리이다.
물론 REMARK부터 시작해서 온갖 잡 칼럼들이 다 모여 있다.


이 테이블로 아주 간단한 칼럼 몇개를 추출해서 테이블 OMM_OUT_HIST_MAIN 을 만들어 보겠다.

========================================================================
SELECT COM_CD, DIV_CD, BILL_SHEET_NO, ITEM_ID, STORE_CD, OUT_DT, CREATE_CLASS, SLIP_CLASS_CD
  INTO OMM_OUT_HIST_MAIN  
  FROM OMM_OUT_HIST
========================================================================


그리고 조건을 주어 검색해 보겠다.

========================================================================
SET STATISTICS IO ON
SET STATISTICS TIME ON

SELECT COM_CD, DIV_CD, BILL_SHEET_NO, ITEM_ID, STORE_CD, OUT_DT, CREATE_CLASS, SLIP_CLASS_CD 
  FROM OMM_OUT_HIST 
 WHERE OUT_DT >= '20140101' AND OUT_DT <= '20140131'

SET STATISTICS IO OFF
SET STATISTICS TIME OFF
========================================================================
테이블 'Workfile'. 검색 수 0, 논리적 읽기 수 0, 물리적 읽기 수 0, 미리 읽기 수 0, LOB 논리적 읽기 수 0, LOB 물리적 읽기 수 0, LOB 미리 읽기 수 0.
테이블 'Worktable'. 검색 수 0, 논리적 읽기 수 0, 물리적 읽기 수 0, 미리 읽기 수 0, LOB 논리적 읽기 수 0, LOB 물리적 읽기 수 0, LOB 미리 읽기 수 0.
테이블 'omm_out_hist'. 검색 수 3, 논리적 읽기 수 76495, 물리적 읽기 수 6, 미리 읽기 수 76252, LOB 논리적 읽기 수 0, LOB 물리적 읽기 수 0, LOB 미리 읽기 수 0.

 SQL Server 실행 시간: 
 CPU 시간 = 8549ms, 경과 시간 = 14333ms
========================================================================

-> 10만건에 14초의 시간이 걸렸다.




========================================================================
SET STATISTICS IO ON
SET STATISTICS TIME ON

SELECT COM_CD, DIV_CD, BILL_SHEET_NO, ITEM_ID, STORE_CD, OUT_DT, CREATE_CLASS, SLIP_CLASS_CD 
  FROM OMM_OUT_HIST_MAIN 
 WHERE OUT_DT >= '20140101' AND OUT_DT <= '20140131'

SET STATISTICS IO OFF
SET STATISTICS TIME OFF
========================================================================
SQL Server 구문 분석 및 컴파일 시간: 
   CPU 시간 = 0ms, 경과 시간 = 0ms.

(215332개 행이 영향을 받음)
테이블 'OMM_OUT_HIST_MAIN'. 검색 수 1, 논리적 읽기 수 40189, 물리적 읽기 수 0, 미리 읽기 수 40122, LOB 논리적 읽기 수 0, LOB 물리적 읽기 수 0, LOB 미리 읽기 수 0.

 SQL Server 실행 시간: 
 CPU 시간 = 1186ms, 경과 시간 = 6977ms

 SQL Server 실행 시간: 
 CPU 시간 = 0ms, 경과 시간 = 0ms
========================================================================

-> 같은 데이터로 10만건에 7초의 시간이 걸렸다.



즉, 테이블이 커지면, 즉 칼럼의 갯수가 커지면 물리적 데이터가 적은 테이블이 속도가 더 빠르다는 결론이다.

이것은 확실히 유의미한 데이터 이다.



자 그럼 거의 풀 스캔해보자. 
총 3백6시만건 쯤 되는데, 3백만건 조회해 보자.

========================================================================
SET STATISTICS IO ON
SET STATISTICS TIME ON

SELECT COM_CD, DIV_CD, BILL_SHEET_NO, ITEM_ID, STORE_CD, OUT_DT, CREATE_CLASS, SLIP_CLASS_CD 
  FROM OMM_OUT_HIST 
 WHERE OUT_DT >= '20100101' AND OUT_DT <= '20140131'

SET STATISTICS IO OFF
SET STATISTICS TIME OFF
========================================================================
SQL Server 구문 분석 및 컴파일 시간: 
   CPU 시간 = 0ms, 경과 시간 = 0ms.

(2993323개 행이 영향을 받음)
테이블 'omm_out_hist'. 검색 수 1, 논리적 읽기 수 236928, 물리적 읽기 수 0, 미리 읽기 수 233244, LOB 논리적 읽기 수 0, LOB 물리적 읽기 수 0, LOB 미리 읽기 수 0.

 SQL Server 실행 시간: 
 CPU 시간 = 7348ms, 경과 시간 = 81681ms

 SQL Server 실행 시간: 
 CPU 시간 = 0ms, 경과 시간 = 0ms
========================================================================

-> 약 1분 21초 걸렸다.



그럼 캄럼을 줄인 테이블을 조회해보자.

========================================================================
SET STATISTICS IO ON
SET STATISTICS TIME ON

SELECT COM_CD, DIV_CD, BILL_SHEET_NO, ITEM_ID, STORE_CD, OUT_DT, CREATE_CLASS, SLIP_CLASS_CD 
  FROM OMM_OUT_HIST_MAIN 
 WHERE OUT_DT >= '20100101' AND OUT_DT <= '20140131'

SET STATISTICS IO OFF
SET STATISTICS TIME OFF
========================================================================
SQL Server 구문 분석 및 컴파일 시간: 
   CPU 시간 = 0ms, 경과 시간 = 0ms.

(2993323개 행이 영향을 받음)
테이블 'OMM_OUT_HIST_MAIN'. 검색 수 1, 논리적 읽기 수 40189, 물리적 읽기 수 0, 미리 읽기 수 0, LOB 논리적 읽기 수 0, LOB 물리적 읽기 수 0, LOB 미리 읽기 수 0.

 SQL Server 실행 시간: 
 CPU 시간 = 6412ms, 경과 시간 = 79694ms

 SQL Server 실행 시간: 
 CPU 시간 = 0ms, 경과 시간 = 0ms
========================================================================

-> 약 1분 19초 걸렸다.


즉, 풀데이터를 스캔한다면 결과값이 유의미하지 않다는 결론이다.






또한, 데이터의 양이 어느 정도이냐에 따라서 속도가 빨라지기도 느려지기도 한다.


13만건 정도의 데이터를 조회한다고 가정하면,
테이블 'omm_out_hist'. 검색 수 3, 논리적 읽기 수 75550, 물리적 읽기 수 0, 미리 읽기 수 0, LOB 논리적 읽기 수 0, LOB 물리적 읽기 수 0, LOB 미리 읽기 수 0.
 SQL Server 실행 시간: 
 CPU 시간 = 7192ms, 경과 시간 = 10377ms

VS

테이블 'OMM_OUT_HIST_MAIN'. 검색 수 1, 논리적 읽기 수 40189, 물리적 읽기 수 0, 미리 읽기 수 0, LOB 논리적 읽기 수 0, LOB 물리적 읽기 수 0, LOB 미리 읽기 수 0.

 SQL Server 실행 시간: 
 CPU 시간 = 1092ms, 경과 시간 = 4620ms


즉, 10대 4.5초 정도로, 유의미한 속도 향상이 있지만,



행의 수를 극단적으로 낮추면, 즉, 3만건 이내를 조회한다고 가정하고 쿼리를 날리면

테이블 'omm_out_hist'. 검색 수 1, 논리적 읽기 수 115776, 물리적 읽기 수 0, 미리 읽기 수 0, LOB 논리적 읽기 수 0, LOB 물리적 읽기 수 0, LOB 미리 읽기 수 0.

 SQL Server 실행 시간: 
 CPU 시간 = 530ms, 경과 시간 = 978ms

VS 

(28412개 행이 영향을 받음)
테이블 'OMM_OUT_HIST_MAIN'. 검색 수 1, 논리적 읽기 수 40189, 물리적 읽기 수 0, 미리 읽기 수 0, LOB 논리적 읽기 수 0, LOB 물리적 읽기 수 0, LOB 미리 읽기 수 0.

 SQL Server 실행 시간: 
 CPU 시간 = 858ms, 경과 시간 = 1672ms

로 오히려 반대의 경우도 발생한다.



즉, 데이터 정규화를 거친 테이블이 반드시 속도를 향상시켜주는 것은 아니라는 것이다.





1 2 3 4 5