수치 부적합 0 4 736

by gopdan [SQL Query] ora-01722 [2018.08.23 13:47:39]


a 테이블의 생년월일 컬럼이 varchar2 인데 '*'이런값들도 들어있어요 

그래서 

select * from (select substr(생년월일,1,4) age  from a where 생년월일 !='*') where to_number(age) <=19 

하면 필터링 된값으로 숫자변환하는거라  될줄 알았는데 수치부적합 에러가 떨어지네요

regexp_replace  로 해결하긴 했는데 저렇게해도 필터링이 되는게 아닌걸가요?

by 마농 [2018.08.23 14:05:59]

쿼리 작성한 대로 실행되는게 아니라
쿼리 변환 과정을 통해 최적화를 시킨 후에 실행됩니다.
쿼리 변환 중에 뷰머징이 실행된 것입니다.
뷰머징은 인라인뷰를 메인쿼리로 합치는 것입니다.

뷰머징이 안되도록 하는 방법으로 힌트주기 방법이 있고
 - 인라인뷰 안에 힌트 주기. /*+ no_merge */
뷰머징이 불가능한 쿼리로 만드는 방법이 있습니다.
 - ROWNUM, DISTINCT, GROUP BY, UNION 등등.

애초에 숫자 변환이 필요한건지 의문이네요?
년도 4자리 잘라왔는데 왜 숫자 두자리랑 비교하죠?
컬럼을 숫자로 가공하여 숫자와 비교하지 마시고
컬럼은 그대로 두고 문자 4자리와 비교한다면?
애초에 이런 문제가 발생하지 않았을 것입니다.


by gopdan [2018.08.23 14:49:19]

마농님 감사드립니다 마지막 조건은 제가 잘못기입했네요^^ 특정일에 나이를 확인해야 되는거였는데  감사합니다


by 신이만든지기 [2018.08.23 14:53:06]
WITH T AS (
 SELECT '20010101' BIRTHDAY FROM DUAL UNION ALL
 SELECT '19820101' BIRTHDAY FROM DUAL UNION ALL
 SELECT '*' BIRTHDAY FROM DUAL UNION ALL
 SELECT '19990101' BIRTHDAY FROM DUAL
)
SELECT FLOOR(MONTHS_BETWEEN(SYSDATE, TO_DATE(BIRTHDAY, 'YYYYMMDD')) / 12) AGE
     , BIRTHDAY
  FROM T
 WHERE BIRTHDAY !='*'
   --AND FLOOR(MONTHS_BETWEEN(SYSDATE, TO_DATE(BIRTHDAY, 'YYYYMMDD')) / 12) <= 19
   AND BIRTHDAY <= TO_CHAR(ADD_MONTHS(SYSDATE, -19 * 12), 'YYYYMMDD')

이런식으로 해보세요.

 


by 마농 [2018.08.23 15:35:33]

신이 만든 지기님 방식을 보면
 - birthday 를 가공하여 비교하는 방식을 주석처리하고
 - birthday 를 그대로 두고 sysdate 을 가공하여 비교하고 있습니다.
에러 발생 요인도 없애고 컬럼을 가공하는 비효율도 줄이는 방법입니다.

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