sql 단일행함수 - 문자, 숫자, 날짜, 변환함수

jinkyung·2021년 1월 15일
0

DBMS

목록 보기
3/21


--단일 행 함수 - 문자함수
--; 프로그래머는 복잡한 SQL 문의 이해나
--  오라클이 제공하는 함수를 몰라도 사용에는 문제가 없다
--  But, SQL 문을 잘 이해해야 되는 이유가 있다
--  1) 데이터를 프로그램에서 가공처리하는 것보다
--     DBMS에서 처리해서 결과만 받아오는 것이
--     성능상 훨씬 낫다
--  2) 아키텍처 면에서 프로그램은 받아온 결과를
--     보여주는데 주력하고, DBMS는 데이터를 저장/처리
--     에 집중하면 둘 간에 적정한 역할의 분리가 이루어
--     지므로 유연성이 증대된다
--     (프로그램과 DBMS가 느슨한 연결이 되어서
--     변경/유지보수에 좋다)

--문자함수
--LOWER 문자열을 소문자로 변환한다
--UPPER 문자열을 대문자로 변환한다
--INITCAP 첫문자만 대문자로 나머지는 소문자로

1)ERP 부서가 있는 지역을 검색한다
SELECT * FROM dept;

SELECT loc "ERP 부서 지역", dname 부서명
FROM dept 
WHERE UPPER(dname) ='ERP';


SELECT loc "ERP 부서 지역", dname 부서명
FROM dept 
WHERE LOWER(dname) ='erp';


SELECT loc "ERP 부서 지역", dname 부서명
FROM dept 
WHERE INITCAP(dname) ='Erp';


--문자연산함수
--SUBSTR 문자열내에 지정된 위치의 문자열을 반환
--        SUBSTR('oracle', 1, 2) => or               --오라클은 첫번째가 1.
--LENGTH 문자열의 길이를 반환
--        LENGTH('oragle') => 6
--INSTR 지정된 문자의 위치를 리턴
--    a라는 글짜가 몇번째에 있는지
--      INSTR('oracle', 'a') => 3
--TRIM 접두어나 접미어를 잘라낸다 (많이 쓰임)
-- o라는 글자 잘라내라
--     TRIM('o' FROM 'oracle') => racle
--LPAD, RPAD 지정된 문자열의 길이만큼 빈부분에
--           문자를 채운다
--     10글자 중 *을 왼쪽에 패딩해라
--           LPAD('20000', 10, '*')
--           => *****20000

2)부서의 명과 위치를 하나의 컬럼으로 검색한다
--CONCAT는 문자열을 연결해주는 함수지만
--잘 사용하지 않는다
--왜냐하면 || 을 더 많이 사용한다

CONCAT ('김','연아') => 김연아

SELECT CONCAT(dname, ' '||loc)
FROM dept;

SELECT dname||' '||loc      --연산자가 함수보다 속도가 더 빠름.
FROM dept;
 
 
3) 부서명과 길이를 출력하라
SELECT dname, LENGTH(dname)
FROM dept;



--4)SUBSTR함수를 이용해서 컬럼에 일부 내용만을 검색한다
SELECT ename, SUBSTR(ename, 2),   -- 2번째 글자부터
              SUBSTR(ename,-2),   -- 뒤에서 2번째 글자부터
              SUBSTR(ename,1, 2),   -- 1번째 글자부터 2글자
              SUBSTR(ename,-2, 2)    -- 뒤에서 2번째 글자부터 2글자
FROM emp;
              


--5)사원 이름에 'a'가 나타나는 위치를 출력한다
SELECT INSTR('database','a'),    -- 처음부터
      INSTR('database','a',3),     -- 3이후
      INSTR('database','a',1,3)       -- 1이후 3번째 보이는 위치
FROM dual;

SELECT * FROM emp;

SELECT ename, INSTR(ename, '이')
FROM emp;


--6)TRIM 함수를 이용 다양한 방법으로 문자열을 검색한다
-- 주로 공백문자 없앨 시 많이 사용.
-- 입력 시 '홍길동' 이렇게 입력하지 않고 ' 홍길동' , '홍길동 ' 입력되는 경우 
-- ename='홍길동'; 검색시 검출이 안된다.
-- TRIM(ename)을 하면 앞뒤의 공백 문자를 제거해준다.

SELECT TRIM('남' from '남기남'),      --앞뒤 모두
       TRIM(leading '남' from '남기남'),  --앞에서 잘라라
        TRIM(trailing '남' from '남남남기남남남')  --뒤에서 잘라라
FROM dual;


-- 7)이름과 급여를 각각 10컬럼으로 검색한다
SELECT eno, RPAD(ename, 10, '*'), LPAD(sal, 10, '*')
FROM emp;


-- 8)부서명의 마지막 글자를 제외하고 검색한다
SELECT dno, SUBSTR(dname, 1, LENGTH(dname)-1)   --dname을 첫번째부터 해당 길이보다 작을때까지 추출해라
FROM dept;



--문자치환함수
--TRANSLATE : 문자단위 치환된 값을 리턴한다
--            TRANSLATE('oracle', 'o', '#')
--            => #racle
--REPLACE : 문자열단위 치환된 값을 리턴한다
--            REPLACE('oracle', 'or', '##')
--            => ##acle

-- REPLACE를 더 많이 쓴다

--9) 
SELECT TRANSLATE('World of Warcraft', 'Wo', '-*') Translate,  --한 글자씩
        REPLACE('World of Warcraft', 'Wo', '--') Replace  --연속적으로 나올 때
FROM dual;

내용을 입력하세요.


*숫자 , 날짜 함수


/*

단일 행 함수 - 숫자, 날짜형 함수

ROUND : 그냥 쓰면 소수점을 반올림해서 정수로
        ROUND(m, n)
        n자리까지 반올림한다
        ROUND(123.4567, 3) => 123.457
TRUNC : TRUNC(m, n)
        n자리 미만을 절삭한다
        TRUNC(123.4567, 3) => 123.456
MOD : MOD(m, n)
      m을 n으로 나눈 나머지 계산한다
      MOD(10, 4) => 2
POWER : POWER(m, n)
        m의 n승 계산한다
        POWER(2, 4) => 16
CEIL  : CEIL(m)
        m보다 큰 가장 작은 정수를 찾는다
        CEIL(2.34) => 3
FLOOR : FLOOR(m)
        m보다 작은 가장 큰 수를 찾는다
        FLOOR(2.34) => 2
ABS : ABS(m)
      m의 절대값을 계산한다
      ABS(-4) => 4
SQRT :  SQRT(m)
        m의 제곱근을 계산한다
        SQRT(9) => 3
SIGN : SIGN(m)
        m이 음수일 때 -1, 양수일 때 1, 0이면 0을 반환
        SIGN(-3) => -1
        
*/
        
--1)다양한 숫자 함수를 이용한 결과를 확인한다
SELECT ROUND(98.765), TRUNC(98.765),
       ROUND(98.765, 2), TRUNC(98.765, 2)
FROM dual;

SELECT MOD(19, 3), MOD(-19, 3)
FROM dual;

--2)부서의 연봉을 계산한다. 단 100단위 미만은 절삭한다
SELECT eno, ename, TRUNC(sal*12+NVL(comm, 0), -2) 연봉
FROM emp;

SELECT TRUNC(19786.786, 2), TRUNC(19786.786, -2)
FROM dual;
        
        
--날짜 함수

--3)현재 시간을 검색하자
SELECT sysdate
FROM dual;

ALTER SESSION SET nls_date_format='YYYY/MM/DD:HH24:MI:SS';

SELECT sysdate
FROM dual;

--4)김연아의 
--오늘 날짜, 입사 일자, 입사일로부터 오늘까지 기간,
--입사일 이후 100일이 지난날 등을 검색하고
--날짜 연산의 결과를 보자

ALTER SESSION SET nls_date_format='YY/MM/DD';

SELECT sysdate, hdate, sysdate-hdate, hdate+100
FROM emp
WHERE ename='김연아';

SELECT sysdate, hdate, TRUNC(sysdate-hdate), hdate+100
FROM emp
WHERE ename='김연아';


--날짜 + 숫자 = 날짜(일수 이후 날짜)
--날짜 - 숫자 = 날짜(일수 이전 날짜)
--날짜 + 숫자/24 = 날짜 (시간을 더한 날짜)
--날짜 - 날짜 = 숫자 (두 날짜 간에 차(일수))
--
--날짜 함수는 주로 회계 정산시 많이 사용한다
--ERP 솔루션, SI 회계


/*
YYYY : 년도
MM : 월
DD : 날짜
HH : 시간
MI : 분
SS : 초
        
ROUND : ROUND(날짜, 형식)
        형식에 맞추어 반올림한 날짜를 반환한다
        ROUND(sysdate, 'DD') => 2020/02/26
TRUNC : TRUNC(날짜, 형식)
        형식에 맞추어 절삭한 날짜를 반환한다
        TRUNC(sysdate, 'YYYY') => 2020/01/01
MONTHS_BETWEEN : MONTHS_BETWEEN(날짜1, 날짜2)
                 두 날짜간의 기간을 월 수로 계산한다
                 MONTHS_BETWEEN('2020/03/01', '2020/04/01')
                 => 1
ADD_MONTHS : ADD_MONTHS(날짜, n);
             날짜에 n달을 더한 날짜를 계산한다
             ADD_MONTHS('2020/03/01', 23)
             => '2022/02/01'
NEXT_DAY : NEXT_DAY(날짜, 요일)
           날짜 이후 지정된 요일에 해당하는 날짜를 계산
           요일 표현은 'sun', '일요일', 1과 같이
           다양한 표현이 가능하다
LAST_DAY : LAST_DAY(날짜)
           날짜를 포함한 달의 마지막 날짜를 계산
           LAST_DAY('2020/02/25') => 2020/02/29        
*/

--5) 숫자와 날짜를 반올림하여 출력한다
-- yy12월이니까 반올림
-- mm 12월 1일이니까 1일은 반올림해봤자 초기화돼서 1일로 나옴
-- 지금 오후 12시가 지났기 때문에 12월 2일로 반올림
SELECT sysdate, ROUND(sysdate, 'YY'),
      ROUND(sysdate, 'MM'),
      ROUND(sysdate, 'DD')FROM dual;

--6) 숫자와 날짜를 절삭하여 출력한다
SELECT sysdate, TRUNC(sysdate, 'YY'),
      TRUNC(sysdate, 'MM'),
      TRUNC(sysdate, 'DD')FROM dual;

--7) 김연아가 오늘까지 일한 일수를 검색한다
--입사일을 포함하기 위해 +1을 해줬다
SELECT TRUNC(sysdate, 'DD') - TRUNC(hdate, 'DD')+1 "일한 날"
FROM emp
WHERE ename='김연아';


--8) 20번 부서 직원들이 현재까지 근무한 개월 수를 검색한다
--소수점을 자르기 위해 TRUNC를 사용.
SELECT eno, ename, TRUNC(MONTHS_BETWEEN(sysdate, hdate)) 근무개월
FROM emp
WHERE dno='20';


--9) 20번 부서원들이 입사 100일째 되는 날과 10년째 되는 날을 검색한다
--입사 당일 포함이므로 99를 더했다.
SELECT eno, ename, hdate 입사일, 
hdate+99 "입사 100일째", 
ADD_MONTHS(hdate, 10*12) "입사 10년째 되는 날"     --10*12개월 = 10년
FROM emp
WHERE dno='20';


--10) 20번 부서원들이 입사한 이후 첫 번째 일요일을 검색한다
SELECT eno, ename, hdate, 
      NEXT_DAY(hdate, '일요일') "입사 후 첫번째 일요일"   --해당되는 이후의 요일검색시 사용
FROM emp
WHERE dno='20';


--11) 20번 부서원들의 입사한 달의 마지막 날짜와
--입사한 달에 근무 일수를 검색한다  => +1을 해야한다.
--(단 입사일은 근무일에서 제외한다) => +1을 해주지 않아도 된다.
SELECT eno, ename, hdate, LAST_DAY(hdate) "입사한 달 마지막 날짜" ,
       LAST_DAY(TRUNC(hdate))-TRUNC(hdate) "입사한 달 근무일 수"
FROM emp
WHERE dno='20';
내용을 입력하세요.


*변환함수


/*
단일 행 함수 - 변환 함수

날짜 출력 형식
년 : YYYY : 네자리로 표현된 년도(1999, 2020, 2011)
     YY   : 두자리로 표현된 년도(99, 20)
            앞에 두자리는 현재 년도를 사용한다
            99년은 2099년을 의미한다
     RR   : 두자리로 표현된 년도(99, 20)
            앞에 두자리는 현재 년도와 가까운 년도를 
            사용한다
            99년은 1999년, 20년은 2020년
월  MM    : 두자리 숫자로 표현된 월 (03, 04)
   MONTH : 영문이나 한글로 표현된 월(MARCH, APRIL, 3월)
   MON   : 약자로 표현된 영문 및 한글 월(MAR, APR, 3월)
           한글인 경우는 MONTH 와 동일하다
일  DD   : 두자리 숫자로 표현된 일자(01, 02)
   DAY   : 영문이나 한글요일(SUNDAY, MONDAY, 일요일)
   DY   : 약자로 표현된 요일(SUN, MON, 일, 월)
시  HH24 : 1시에서 24시까지 표현
    HH   : 1시에서 12시까지 표현
            정확한 표현을 위해 AM/PM을 추가하는 것이 좋다
분  MI   : 두자리 분 표시
초  SS   : 두자리 초 표시
   SSSS : 하루를 초로 환산한 다음 표현(0-86399)
오전/오후 AM/PM : 오전 오후 표기

숫자 출력 형식
9   숫자의 출력 폭지정(자리수가 부족하면 생략)
0   선행 0표기(자리수를 반드시 맞춘다)
$   화폐 표기(달러)
L   지역 화폐 표기(각 국가 코드에 따라 다르다)
,   쉼표 위치 지정
.   마침표 위치 지정
MI  음수의 -기호를 오른쪽에 표기
EEEE 실수 표현법을 이용

변환 함수
TO_CHAR : 날짜나 숫자를 문자로 변환한다
          출력 데이터 형식을 지정한다(출력 포맷)
          TO_CHAR(날짜, 출력형식)
          TO_CHAR(숫자, 출력형식)
TO_DATE : 데이터를 날짜형으로 해석한다
          TO_DATE(문자, 해석형식)
TO_NUMBER : 데이터를 숫자로 해석한다
            대부분의 경우 오라클의 자동 형변환에 의해
            숫자로 읽을 수 있는 문자는 자동 변환됨으로
            잘 사용하지 않는다
            SQL 보다 PL-SQL에서 가끔 사용한다
*/

--1) 현재 날짜를 다양한 형식으로 출력해보자
SELECT TO_CHAR(sysdate, 'YYYY/MM/DD') 날짜,
       TO_CHAR(sysdate, 'YYYY/MM/DD:HH24:MI:SS') 날짜,
       TO_CHAR(sysdate, 'YY/MM/DD:HH:MI:SS AM') 날짜
FROM dual;

SELECT TO_CHAR(sysdate, 'DD MONTH YYYY') 날짜
FROM dual;

SELECT 2+3 FROM dual;

SELECT TO_CHAR(sysdate, 'DAY Mon YY') 날짜
FROM dual;

SELECT TO_CHAR(sysdate, 'DY Mon YY') 날짜   
FROM dual;

-- 오늘은, 월, 일 입니다 가 문자열이고 YYYY MM DD는 서식문자.
SELECT TO_CHAR(sysdate, '"오늘은 "YYYY"년 "MM"월 "DD"일 입니다."')
FROM dual;

--2) 20번 부서 사원의 입사일을 다음의 형식으로 검색한다
'XXX 사원의 입사일은 XXXX년 XX월 XX일입니다.'
SELECT ename||' 사원의 입사일은 '||
      TO_CHAR(hdate, 'YYYY"년 "MM"월 "DD"일 입니다."') 입사일
FROM emp
WHERE dno='20';

--3) 다양한 형식으로 숫자를 출력해 보자
--   9는 숫자의 출력 폭 지정 (포맷)
SELECT TO_CHAR(12345.678, '999,999.99999') 숫자   --소수점 이하 다섯자리로 표현해라.
FROM dual;
      
SELECT TO_CHAR(12345.678, '099,999.999') 숫자     --앞에 0을 표시하라.
FROM dual;   

SELECT TO_CHAR (12345.678, '9,9999.9') 숫자
FROM dual;

--소수점 앞자리가 부족하면 출력장애 발생된다. 5자리인데 형식에 4자리밖에 없음.
SELECT TO_CHAR (12345.678, '9,999.9') 숫자   
FROM dual;

SELECT TO_CHAR (1234, '$999,999') 숫자   
FROM dual;

SELECT TO_CHAR (1234, 'L999,999') 숫자  
FROM dual;

SELECT TO_CHAR (-1234, '999,999MI') 숫자   
FROM dual;

--네자리만 표기하고 나머지는 EEEE표기법 표시해라. => +8이면 오른쪽으로 8칸. 음수면 왼쪽(앞)으로 8칸.
SELECT TO_CHAR (123456789, '9.999EEEE') 숫자   
FROM dual;

--4) 20번 부서의 사원의 보너스가 급여의 몇 퍼센트인지 검색한다
--급여는 월간급여이고 보너스는 연간 보너스이다
--보너스가 null 인 경우는 0으로 환원해서 검색한다
SELECT eno, ename,
      TO_CHAR(NVL(comm,0)/(sal*12)*100,'99')||'%' 급여비율   --99:두자리로 표현
FROM emp
WHERE dno='20';


SELECT eno, ename,
       ROUND(NVL(comm,0)/(sal*12)*100)||'%' 급여비율   --
FROM emp
WHERE dno='20';

            
--5) 1992년 이전에 입사한 사원의 정보를 검색하자
SELECT eno, ename, hdate
FROM emp
WHERE hdate < TO_DATE('1992/01/1','YYYY/MM/DD');

--세션의 출력 형식이 'DD-MON-YY'등과 같이 달라진다면    
--WHERE hdate < '1992/01/01' 방식의 비교는
--정상적인 실행을 보장할 수 없다
--이럴 때는 세션의 출력형식을 변경하던지 아니면
--비교 문자열을 출력형식에 맞추던지 해야 한다.
--이것은 날짜의 표기 방식이 OS나 오라클의 지원 언어 등에
--따라 달라져서 발생하는 문제이다.
--SQL 문장을 작성하는 개발자가 세션의 날짜 형식과 무관한
--SQL 문장을 작성하고 싶다면 반드시 TO_DATE함수를 사용해서
--비교해야 한다. 
--TO_DATE 로 작성된 SQL 문은 어떤 오라클 환경에서도 동일한
--사용이 보장된다.
--이것을 '이식성이 좋다' 라고 표현한다

--TO_DATE 함수를 사용하면 date라는 자료형으로 만들어주기 때문에 비교가 가능하다
            

0개의 댓글