오라클 문자 자르기.. ( 내용 유. 고정문자 텍스트파일.. ) 0 22 8,596

by 홈런쓰 [2017.01.13 09:13:26]


고정문자텍스트파일을 받았는데요

통으로  clob  컬럼에 적재를 하고요. 고정문자텍스트 레이아웃을 받은 내용으로 문자를 잘랐는데요..

 

substr, substrb 모두 문자가 제대로 잘리지 않네요..

엑셀에서는 midb 함수를 이용하면 잘 잘리는데 말이죠..

 

엑셀에서 midb 와  오라클의 substrb 같은 기능 아닌가요? 바이트로 계산하여 문자를 자르는..

엑셀에서 lenb  값과  오라클에서  lengthb  값도 다르더군요..

 

원인이 무엇일까요.. 답변 부탁드립니다 !~

by jkson [2017.01.13 09:33:47]

clob 컬럼을 substr한다는 말씀이신가요?

11.2.0.3.0 기준 substr은 잘 되고 substrb는 안 되네요.

substrb는

substrb(to_char(substr(컬럼,1,10)),1,10)

혹은

substrb(dbms_lob.substr(컬럼,10),1,10)

이런 식으로 구현하면 될듯합니다.

더 좋은 방법이 있는지는 모겠네요.

 

아.. 제대로 안 잘린다고 하신 거 보니.. 자르기는 잘랐는데 원하는 결과가 아닌 것 같네요?

substrb가 바이트로 자르는 것 맞는데 어떻게 잘 안 되신다는 건지..


by 홈런쓰 [2017.01.13 10:33:57]

답변 감사합니다

to_char, dbms_lob.substr  모두 사용해보았는데 잘 안되네요..

밑에 댓글에 상세내용 달아 놓았습니다~ ^^


by 마농 [2017.01.13 09:40:20]

실제 데이터를 예로 들어 주세요.

원본데이터, 사용쿼리, 결과데이터, 원하는 결과


by 홈런쓰 [2017.01.13 10:32:12]

우선 답변 감사합니다.  실제데이터 양식 알려드리겠습니다..

 

00000000000    0000  00000000000000                                                            000                                        00000000000000000                                        0000                                        00000                                                  00000000                                                                                        가가가가가가가가가가                                                                      가가가가가  나나              다다다00000000                                                        가가                                                      가가가                                                            0000000000000000000                                            가가가         000000000000 ZZZZZZZZZ00 00000000000000              가가가00000000000000ZZZZZZZZZ000 ZZZZZZZZZ00 ZZZZZZ000    ZZZZZZ0000000.0000000000000000000000.00000000000000000000000.000000000

 

실제데이터고요. 텍스트파일을 받아서 db clob 컬럼에 적재하였습니다.

결과값은 "나나", "다다다"(앞뒤로 공백은 존재해도 됩니다. 데이터가 그렇게 되어있습니다.) 를 받고 싶습니다..

엑셀  midb 함수를 사용하면 제대로 나오는데 디비에서는 전혀 다른 결과를 가져오네요..결과값을 못 얻네요..

사용 쿼리입니다.

SELECT
    SUBSTRB(TO_CHAR(DATA),492, 6) AS "나나"
    , SUBSTRB(TO_CHAR(DATA),498, 19) AS "다다다"           
FROM DATA_TABLE
;

 


by 마농 [2017.01.13 10:43:01]

올려주신 데이터를 보면
(492,  6) => '나나  '
(498, 19) => '            다다다0'
(498, 20) => '            다다다00'
이렇게 나오네요.
숫자를 정확하게 알려주신게 맞는지?
전혀 다른 값은 뭐가 나오나요? 공백까지 포함해서 정확하게 알려주세요.
오라클 버전은 어떻게 되나요?
 


by jkson [2017.01.13 10:52:38]

저는 (492,6) => '  나나 '

(498,19) => '             다다다'

(498,20) => '             다다다0'

네요. 왜 한 칸이 차이가 날까요?..

별개로.. 생각해보니까요.. 혹시나 작성자 서버 설정이 한글 한 글자가 3byte가 아닐까.. 하는 생각이 드네요.

select * from nls_database_parameters where parameter like '%CHARACTERSET%'

작성자님 이 쿼리 실행하셔서 확인 부탁드립니다.


by 마농 [2017.01.13 10:58:39]

아 그러네요. 잘못 계산 했네요. ^^


by 홈런쓰 [2017.01.13 10:58:39]

오라클 버전은 11.2.0.3.0

케릭터셋은 AL32UTF8 입니다.

뽑으신 데이터 보면

(492,  6) => '나나  ' 이 부분은 제대로 나오는것 같네요

여기 제대로 나오는 것 보면 뒤 부분은 레이아웃을 다시 확인해봐야 할 것 같습니다.

(498, 19) => '            다다다0'
(498, 20) => '            다다다00'

이 부분은 레이아웃을  확인 해 보겠습니다.

제가 사용한 쿼리로는 결과값이

(492,  6) => '  다다다0'

(498, 19) => '0000000            '
이렇게 나오네요 ..
  

 


by jkson [2017.01.13 11:01:37]

홈런쓰님 UTF8/AL32UTF8은 한글 한 글자가 3BYTE 입니다. 그러면 원하시는 결과를 얻으려면.. 어떻게 해야할까요? 산수가 잘 안 되네요;

그리고 또 한 가지.. 데이터가 4000 BYTE가 넘으면 홈런쓰님이 작성하신 방법은 아예 오류가 날테고 제가 알려드린 방법(substrb(dbms_lob.substr(컬럼,10),1,10))도 4000BYTE 이전까지 SUBSTRB하면 오류가 안 나겠지만 그 이상이 되면 오류가 나겠네요. 혹시나 4000BYTE 넘는 데이터가 있나요? 있다면 4000BYTE 이후로 SUBSTRB 할 케이스가 있으신지.. CLOB을 쓰신 걸로 봐서는 있을 것 같은데..


by 홈런쓰 [2017.01.13 11:13:34]

jkson  님 말대로 제가 사용하고 있는 케릭터셋은 한글 한글자가 3byte 네요.. 케릭터셋을 변경 안하고 2byte 로 계산하게끔 할 수 있는 방법이 있을까요,,?

데이터 건수가 많아서 혹시나 하고  clob 타입에 적재를 한 것 입니다. 적재를 다 하고 보니 4000byte  이상인 데이터는 없네요 ~


by jkson [2017.01.13 11:23:18]

4000byte가 넘을 일이 없다면 varchar2 타입으로 바꾸시는 게 추후 관리상 편하실 것 같고요.

(clob 타입은 문자열 비교나 여러 함수의 사용 제약이 있어서..패키지 함수 사용해야합니다.)

한글 한 글자가 3byte 면 substrb 뒤에 잘라오는 숫자 부분을 3 byte 기준으로 바꾸시면 되지 않나요?


by 홈런쓰 [2017.01.13 12:42:41]

jkson 님 말대로 뒤에 오는 숫자를 3byte 기준으로 바꾸었는데 공백까지 있으니 데이터가 원하는데로 안잘리네요, 한글이 있는 데이터도 있고, 한글+공백, 공백으로 존재하는 데이터도 있어서요


by jkson [2017.01.13 13:42:11]

3BYTE 환경이 아니라 테스트가 안 되네요. 죄송합니다;


by 홈런쓰 [2017.01.13 14:41:58]

jkson 님 신경써주셔서 감사합니다 ~


by 마농 [2017.01.13 11:09:43]

제 환경에서는 또 다르게 나오네요.

한글이 3Byte 여서 그런 것인데...

-- Version : Oracle Database 11g Express Edition Release 11.2.0.2.0
-- nls_characterset : AL32UTF8
-- nls_nchar_characterset : AL16UTF16
WITH data_table AS
(
SELECT
TO_CLOB(
'00000000000    0000  00000000000000                                                            000                                        00000000000000000                                        0000                                        00000                                                  00000000                                                                                        가가가가가가가가가가                                                                      가가가가가  나나              다다다00000000                                                        가가                                                      가가가                                                            0000000000000000000                                            가가가         000000000000 ZZZZZZZZZ00 00000000000000              가가가00000000000000ZZZZZZZZZ000 ZZZZZZZZZ00 ZZZZZZ000    ZZZZZZ0000000.0000000000000000000000.00000000000000000000000.000000000'
) AS data
FROM dual
)
SELECT SUBSTRB(TO_CHAR(data), 492,  6) x
     , SUBSTRB(TO_CHAR(data), 498, 19) x
     , SUBSTRB(TO_NCHAR(data), 492,  6) y
     , SUBSTRB(TO_NCHAR(data), 498, 19) y
  FROM data_table
;
-- 결과 : '  가 ', '  가가  나나   ', '  ', '         '

 


by 홈런쓰 [2017.01.13 11:14:32]

저와 오라클 버전만 다르고 케릭터셋은 같은 환경이시네요.. 같은 현상인거 같습니다.


by 마농 [2017.01.13 15:23:19]

한글자씩 잘라서 루프돌리시면서 사이즈 체크해가면서 글자를 완성시켜 나가야 할 듯 ㅡ,.ㅡ


by 마농 [2017.01.13 15:37:16]
WITH data_table AS
(
-- 원본 테이블
SELECT 1 no,
TO_CLOB(
'00000000000    0000  00000000000000                                                            000                                        00000000000000000                                        0000                                        00000                                                  00000000                                                                                        가가가가가가가가가가                                                                      가가가가가  나나              다다다00000000                                                        가가                                                      가가가                                                            0000000000000000000                                            가가가         000000000000 ZZZZZZZZZ00 00000000000000              가가가00000000000000ZZZZZZZZZ000 ZZZZZZZZZ00 ZZZZZZ000    ZZZZZZ0000000.0000000000000000000000.00000000000000000000000.000000000'
) AS data
FROM dual
)
, code_table AS
(
-- 잘라올 항목들의 시작위치와 길이를 코드화
SELECT 1 cd, 492 a, 6 b FROM dual
UNION ALL SELECT 2, 498, 19 FROM dual
)
SELECT *
  FROM (SELECT a.no
             , c.cd
             , LISTAGG(v) WITHIN GROUP(ORDER BY lv) v
          FROM (SELECT no
                     , lv
                     , SUBSTR(v, lv, 1) v
                     , SUM(LEAST(LENGTHB(SUBSTR(v, lv, 1)), 2)) OVER(PARTITION BY no ORDER BY lv)
                         - LEAST(LENGTHB(SUBSTR(v, lv, 1)), 2) + 1 x
                  FROM (SELECT no, TO_CHAR(data) v FROM data_table)
                     , (SELECT LEVEL lv FROM dual CONNECT BY LEVEL <= 999)
                 WHERE lv <= LENGTH(v)
                ) a
             , code_table c
         WHERE a.x BETWEEN c.a AND c.a + c.b - 1
         GROUP BY a.no, c.cd
        )
 PIVOT (MIN(v) FOR cd IN (1, 2))
;

 


by 홈런쓰 [2017.01.13 16:57:06]

감사합니다 데이터 잘 잘리네요.. 헌데 row 수가 많아서 결과값이 안나오네요...ㅋㅋㅋ

더 해봐야겠습니다 ~


by 마농 [2017.01.13 17:01:57]

그럴 것 같았어요...900자를 한글자씩 잘라서 처리하다보니...


by jkson [2017.01.13 18:05:23]

substrb(convert(to_char(컬럼), 'KO16KSC5601','AL32UTF8'),1,10) 잘될지는 모르겠습니다.

convert라고 characterset 바꿔주는 함수가 10g부터 있었네요.

CONVERT( '대상 문자열', '타겟 캐릭터셋', '소스 캐릭터셋')

http://docs.oracle.com/cd/E11882_01/server.112/e41084/functions034.htm#SQLRF00620


by 홈런쓰 [2017.01.16 13:04:08]

안그래도 해보았는데 한글이 깨져서 나오드라고요 ~ ㅎㅎ

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입