Database

[Database] Ch2.테이블 생성 및 데이터 조작(DML) Ch3.데이터검색 Ch4. Stored Function

OptimizerStart 2025. 5. 4. 23:05

데이터 타입

VARCHAR 가변 문자열 cf.VARCHAR2 는 안씀

CHAR 고정 문자열. 1~ 2자리

NUMBER 부동 소수점 38자리까지

 

NUMBER(p,s)

  • 전체 자리수 (점 미포함) p 자리
  • 실수부 개수 s
  • 정수부 최대 자릿수 = p – s전체 7자리, 정수는 7 - 2 = 5자리까지만 가능. 2는 소수자리 개수. 정수만 7자리 전체 쓸 수 없음.
  • ex. NUMBER(7,2)
  • 음수 저장 가능

DATE 날짜.

  • 시간 : 연속적, 정수
    • DB 저장 시 정수형태로 저장됨. 사람이 읽을 떄만 쪼개서 사용함.

LONG 큰 Text

RAW LONGRAW 큰 Binary

 

SQL 명령어 종류

Data Retrieve 데이터 검색 조회

  • SELECT Read
  • DML은 Write만 가능한 것

Data Manipulation Language DDL 데이터 조작

  • data를 다루는 명령어, 자료구조를 다루는 기능 ex. CH11 컬렉션과 프레임워크
  • INSERT, UPDATE, DELETE Write

Data Definition Language DDL 데이터 정의어

  • DB의 구조를 다루는 명령. 자료구조
  • CREATE, ALTER, DROP, RENAME, TRUNCATE, COMMENT

 

insert

  • 1개의 행(객체)를 삽입
  • cf. update, delete 는 한번에 여러 행(객체) 다룸
  • 테이블 설계시 not null 설정된 값은 필수로 값 삽입해야함.

*

  • 모든 컬럼
    cf. not name 특정 컬럼을 제외하는 명령어는 존재하지 않음

select

  • 출력문
  • 산술식을 적용한 컬럼에 AS로 이름 붙이기
  • [ JAVA ] for 와 print 문
  • 사용 연산자
    • 산술식, AS, || 컬럼 합성, DISTINCT, * (와일드카드)
for(Row r : S_EMP) print(1);
<=> 
select 1 from S_EMP;  // 행의 개수 만큼 1이 들어간 채로 출력

 

스키마 (= 사용자)

  • 객체(테이블, 뷰, 시퀀스)가 어느 사용자에게 속해있는지 구분하기 위해 사용.
    ex. student.s_emp
  • 명령어 delete 해도 commit 안하면 데이터는 유지됨.
  • 문자열 리터럴 ‘’ 작은 따옴표

join = cartisian product × + project π

 

alias

  • 영어 1글자 쓰는 건 이중 따옴표(””) 사용 안해도됨.
  • as 단어 생략 가능
  • 대소문자 구별, 두 단어(띄어쓰기 있는 경우)이상이면 이중 따옴표(””) 반드시 작성
  • 사용 상황
    • select 문에서 산술 연산 수행 시
select name, mailid as E from s_emp; -- O
select name, mailid as "E" from s_emp; -- O
select name, mailid as Email from s_emp; -- O
select name, mailid as Email id from s_emp; -- 오류 발생 
select name, mailid as 이메일 from s_emp; -- O

 

컬럼 합성 ||

  • 컬럼들을 합성하여 하나의 컬럼으로 출력. 문자열 컬럼.
  • 합성할 때 문자열은 ‘’ 단일 따옴표로 작성해야함. 이중 따옴표 오류남
    cf. mysql 에는 없는 연산. concatenate() 함수 이용
select name || ' ' || title as "겹쳐서" from s_emp;
select name || ' ::::' || title as "이름 : 직책"
from s_emp;

distinct

  • 졍렬 필요함. for문 2번이므로 부담이 큼 튜닝 🟢
  • 주의
    • distinct 뒤에 오는 모든 컬럼에 중복제거 적용
select distinct title, name from s_emp; -- distinct 는 title, name 모두 중복 제거함.

 

order by

  • 데이터 정렬
  • 주의사항
    • DISTINCT를 사용한 경우 ORDER BY 절에 지정된 컬럼이 반드시 SELECT 리스트에 포함ORA-01791: SELECT 식이 부적합합니다 
    • [오류 내용] 01791. 00000 - "not a SELECTed expression"
-- where -- filter 
select distinct title from s_emp
where title like '%부장' -- filter java에서는 if(title.endsWith("부장")) 
order by 1 desc, 2 asc ; 
-- order by name asc; -- 왜 오류나냐?

 

 

where

  • 필터
  • [ JAVA ] if문
  • 사용 가능 연산자
    • BETWEEN, IN, NOT IN, LIKE, AND, OR

BETWEEN

1000 ≤ X ≤ 2000 등호 양쪽 포함

형변환

수동(직접) 형변환 to_date(’16/12/31’) ⇔ 문자열 → Date타입 자동 형변환 WHERE start_date < ‘16/12/31’ char → Date타입

  • 자동 형변환 제공 : 문자열 ↔ 숫자 비교 , 문자열 ↔ 날짜 비교
  • ex. 'id' 숫자가 ''로 감싸져서 문자열이면 to_number()를 자동으로 넣어줄까? yes

규칙

  • Oracle에서는 자동 형변환이 가능하지만, 데이터베이스마다 설정이 다를 수 있기 때문에 수동 형변환을 해야함.

IN

[ JAVA ] OR

NOT IN 아무것도 일치하지 않는경우

-- 'id' 숫자가 ''로 감싸져서 문자열이면 to_number()를 자동으로 넣어줄까? yes
select * from s_emp
--where id > '20';-- ok 
where id > to_number('20');

 

와일드 카드

  • % 0~N개 포함
  • _ 1개 포함
  • [퀴즈] '17%'
    • 유사한것을 찾아야 해서 성능 느림 🟢 튜닝
    • %17%, %17 보단 17%빠름. 앞에서 부터 비교해서.

논리 연산자 AND OR

  • AND가 OR보다 우선순위 높음
  • 규칙 괄호 치기

문자형 함수

  • LENGTH(문자값)
    cf. lengthb() byte 단위로 길이 출력. exlengthb(’홍길동’)
  • DB 문자 인코딩
    • 저장 바이트는 인코딩이 결정
    • UTF-8 한글 1글자 3byte (최신 oracle)
    • UTF-16 / EUC -KR 2byte
select length('홍길동') from dual; -- 3
select lengthb('홍길동') from dual;-- 9

 

 

LPAD(문자열1, 전체자릿수, 채울문자)

  • 왼쪽부터 채울문자를 채움.

RPAD(문자열1, 전체자릿수, 채울문자)

  • 오른쪽부터 채울문자를 채움.

 

화면 출력 폭 차이

전각 문자 1글자를 2글자 차지

- 한글, 한자

반각 1글자 차지

 

저장 바이트와 출력 바이트 차이

  • 저장 바이트 수 차이 ⇒인코딩(Character Set)
  • 화면 출력 폭 차이 ⇒전각/반각(East Asian Width), 인코딩도 관여함. 어느 문자표에서 문자를 가져올지 지정.

dual

  • dummy table
  • 단순 함수를 출력해서 확인해볼 때, 임의로 넣을 테이블
    cf.mysql은 select now();

translate(문자값, from대체하고싶은문자 , to대체할결과의문자 )

치환된 결과의 문자 개수 동일

길이

  • from = to : OK
  • from < b : 짤림
  • from > to :OK
select translate('나는이름입니다.', '이름', '개발자') from dual; -- 나는개발입니다. from과 to의 글자가 같아야 치환 됨. 
select translate('나는개발자입니다.', '개발자', '이름') from dual; -- ok. 나는이름입니다.

 

replace(문자값, from바꾸고싶은문자, to바꿀결과문자)

치환된 결과 문자 개수 달라질 수 있음

select replace('Jack and Jul', 'J', 'KUNDOL') from dual; -- KUNDOLack and KUNDOLul. from과 to의 문자 길이가 달라도 됨.

 

 

 

숫자형 함수

오라클에서 NUMBER 타입은 불필요한 0을 생략해서 보여줌. ex.16.112000 → 16.112

 

ROUND(숫자값, a)

  • a > 0 소수점 a자리 기준으로 반올림. 즉, a +1 자리에서 반올림
    • a = 1, 소수점 첫번째 자리 기준으로 반올림, 소수점 두번째자리에서 반올림후 소수점 첫번째 자리까지만 남게 만듦
  • a = 0 소수 첫째 자리에서 반올림. 정수부만 존재
  • a < 0 정수부에서 a자리 기준으로 a + 1 자리에서 반올림
    • a = -1, 10의 자리 기준으로 일의자리 반올림
select round(355.165,4) from dual; -- 355.165. 소수점 넷째자리에서 반올림후 줌. 없으므로 0을 반올림하는듯 1
select round(355.166,4) from dual; -- 다섯째 자리에서 반올림하여 4자리까지 돌려주는데, 넷째, 다섯째 없어서 0은 출력 안함. 
select round(32156.96674,3) from dual; -- 32156.967
select round(32156.96674,0) from dual; -- 32157
select round(32156.96674,-1) from dual; -- 1의 자리를 보고 10의 자리를 올리거나 내림 . 1의 자리에서 반올림 후 1의 자리 이하 버림(소수포함) 32160
select round(32156.96674,-2) from dual; -- 10의 자리를 보고 100의 자리를 올리거나 내림 .10의 자리에서 반올림 후 10의자리 이하 버림. 32200
select round(32156.96674,-3) from dual; -- 100의 자리를 보고 1000의 자리를 올리거나 내림 .100의 자리에서 반올림 후 100의 자리 이하 버림. 32000
select round(32156.96674,-4) from dual; -- 1000의 자리를 보고 10000의 자리를 올리거나 내림 .1000의 자리에서 반올림 후 1000의 자리 이하 버림. 30000
select round(32156.96674,-5) from dual; -- 10000의 자리를 보고 100000의 자리를 올리거나 내림 .

 

 

MOD(숫자값, a)

  • a 숫자값을 나누기 할 수
  • 숫자값 나머지의 부호는 항상 숫자값을 따라감.

mod(19, 0) 0으로 나눌 경우

  • 오라클에서는 나눗셈의 나머지를 구할 수 없는 경우 dividend (나누기 할 수) 를 반환하도록 설계됨. 무한대 아님.
  • cf. 일반 나눗셈 19/0의 경우는 divisor is equal to zero 오류 발생
select mod(19,3) from dual; -- 1
select mod(-30, 4) from dual; -- -2
select mod(19,0) from dual; -- 0. * 무한대가 아니네? 0으로 나눈 나머지인데

 

 

날짜형 함수 ⭕ 중요

ROUND(날짜값, 자리수)

  • 자리수 ’YEAR’, ‘MONTH’, ‘DAY’ ‘mi’
    • 작은 따옴표로 감싸고 있어야함. 안하면 에러 발생
  • 날짜값에는 '25/05/25' 문자 형식으로 오면 에러 발생. 반드시 to_date()로 형변환 해줘야 함. 
    • [에러] ORA-01722: 수치가 부적합합니다 01722. 00000 - "invalid number
now trunc_minute round_minute
2025-04-30 14:23:46 2025-04-30 14:23:00 2025-04-30 14:24:00

 

select round(sysdate , 'dd') from dual; -- 25/05/01 12시 넘으니 내일로 반올림 
select round(sysdate , 'month') from dual; -- 25/05/01  15일 이상이니 반올림. 
select round(sysdate , 'year') from dual; -- 25/01/01
select round(sysdate , 'mi') from dual; -- 25/04/30

select round('25/05/25', 'month') from dual; -- 에러.ORA-01722: 수치가 부적합합니다
-- 01722. 00000 -  "invalid number"

select round(to_date('25/05/25'), 'month') from dual; -- 형변환

 

변환형 함수

 

TO_NUMBER()

  • 문자를 숫자로 변환
  • [ JAVA ] pareInt()

TO_CHAR()

숫자나 날짜를 문자열로 변환

  • 250429 - TO_CAHR( 값, 형식) → “25/04/29” 형식 지정 필수 yyyymmdd
  • 250429 ← to_date( ) - “25/04/29”
  • 형식
    • YYYY, YY(끝자리2개), MON(3자리 영문,SEP), MM(2자리숫자), DD(날짜day, 31), MI(분), SS(초)

 

요소 의미
9 일반적인 숫자. 그외 로 하면 에러남
0 앞의 빈자리 0으로 채움
$ 달러 기호 표시
L 지역 통화 단위. 알아서 출력
. 점 소수점 표시
, 콤마 천단위 표현

 

 

-- 숫자를 문자로 변환
select to_char(3500000, '$1,111,111') from dual; --invalid number format model" 9로 형식을 써야 일반적인 숫자로 인식함.
select to_char(3500000, '$9,999,999') from dual; --  $3,500,000
select to_char(3500000, 'l9,999,999') from dual; --         ₩3,500,000 알아서 지역에 맞게 원 단위 출력함
select to_char(35000, 'l0,999,999') from dual; -- ₩0,035,000 형식으로 지정한 수보다 작으면 0으로 채움
select to_char(35000, 'l0,999.999') from dual; -- #################### 형식 지정에서 정수는 최대 4자리인데, 숫자는 5자리이므로 마스크 길이만큼 # 출력
select to_char(3500, 'l0,999.999') from dual; --         ₩3,500.000

 

 

 

 

TO_DATE()

  • 문자를 날짜(DATE)로 변환
  • DATE 타입: 초단위 정수 ms (1000분의 1초)

 

 

그룹 함수

  • 모든 그룹함수는 null 값을 고려하지 않음. 단, count(*) 제외

주의사항

  • count(*) vs. count (salry) 차이
  • count(*) 행의 개수
  • count(salary) null 제외한 행 개수
    • avg() 계산에서는 나누는 수를 count(*)가 아닌 count(salary) null 제거된 개수임.
select count(*) from ex_test; -- 4
select count(salary) from ex_test; -- 3
select avg(salary ) as "평균" from ex_test; -- 200. avg 계산에서는 나누는 수를 count(*)가 아닌 count(salary) null 제거된 개수임.

 

 

 

nvl(salary, 0)

null값 대신 0으로 저장. oracle 함수.

 

함수를 여러개 겹쳐 사용

안쪽부터 바깥쪽 순서로 적용

-- emp.sal 이 NULL 이면 0으로,  
-- 반올림(Round) 후 천 단위 구분자·소수점 둘째 자리까지 표시
SELECT TO_CHAR(
         ROUND( NVL(sal, 0) , 2 ),        -- NVL → ROUND
         'FM999G999G990D00'               -- → '1,234.50' 같은 포맷
       ) AS formatted_sal
FROM   emp;