전체 글 (135)

728x90

 

수업내용 정리 (MySQL)

 

0. select 처리 순서

  • from (테이블의 존재 유무) -> where (조건 따지기) -> group by (그룹 묶기) -> having (그룹 조건 따지기) -> select (출력 할 데이터 검색/선택) -> order by (정렬)
  • select에서 as로 칼럼 별칭을 지어줬을 경우, order by에서만 사용이 가능하다. (단, 예외의 경우가 있다.)

 

 

1. 그룹 함수

더보기
  • null 값은 제외한다.
  • max(): 가장 큰 값
  • min(): 가장 작은 값
  • count(): 개수
  • sum(): 총합
  • avg(): 평균 값

 

-- 각 부서별 인원수, 최대 급여
select min(sal), max(sal), sum(sal)/count(sal) as 평균, round(avg(sal),1), count(sal) from emp;

 

 

  • group by: 칼럼을 그룹으로 묶는다. 여러 칼럼으로 그룹을 묶을 수 있다.
  • having: group by 이후 조건 따지기

 

select deptno 부서번호, min(sal) min, max(sal) max, round(avg(sal),2) as 평균, count(sal) '사원 수'
from emp
group by deptno order by deptno;

select*from emp group by deptno;	-- 부서번호를 그룹으로 했는데 모든 칼럼을 출력하려고 해서 에러
  • select에 칼럼을 적으려는 경우, 그룹화 한 칼럼만 적을 수 있다.
  • 그룹화하지 않은 다른 칼럼을 적을 경우 에러가 난다.

 

 문제) 

-- 문) 부서별 근무 인원 출력 / 출력 예) 10 3명
select deptno, concat(count(deptno), '명') as 인원 from emp group by deptno order by deptno;
select deptno, concat(count(*), '명') as 인원 from emp group by deptno order by deptno;
  • count(*): 모든 칼럼을 비교해서 null값이 아닌 행의 수를 측정한다.

 

 예제) 

-- 10번 부서를 제외한 부서별 근무 인원 출력
select deptno, concat(count(*), '명') as 인원 from emp
where deptno<>10 group by deptno order by deptno;
-- 10번 부서 제외한 부서, 직급 별 근무 인원, 2명 이상
select deptno, job, concat(count(*), '명') as 인원 from emp
where deptno<>10 group by deptno, job having count(*)>1 order by deptno, job;

 

 문제)

-- 문) 부서 내 직급별 인원수와 최대급여 검색, 부서번호 오름차순 검색
select deptno '부서번호', job '직급', count(*) '인원 수', max(sal) '최대급여'
from emp group by deptno, job order by deptno;
select deptno '부서번호', job '직급', count(*) '인원 수', max(sal) '최대급여'
from emp group by deptno, job with rollup;
  • with rollup: count, min 등 select에서 사용한 칼럼 그룹 단위로 집계 값을 출력한다.
  • 단, order by와 같이 사용하지 못한다.

 

-- 부서별 입사일 1981-01-01 이후 입사한 사원이 2명 이상인 경우
select deptno '부서', count(*) '인원' from emp
where hiredate>'1981-01-01' group by deptno having count(*)>1;
  • hiredate가 날짜이기 때문에 문자열로 '1981-01-01'이라고만 해도 비교가 된다.
  • 부서 별 2명 이상은 그룹을 묶은 후 비교를 할 수 있기 때문에 having으로 조건을 적는다.

 

-- 급여가 1000이상인 사원 중에서 부서별 중위급여가 2500미만이고
 -- 평균 급여가 1200~2000 사이인 최대급여, 최소급여, 중위급여, 평균급여 검색
select deptno '부서', max(sal), min(sal),
	round((max(sal)+min(sal))/2,2) '중위급여',
	round(avg(sal),2) '평균급여', count(*) '인원'
from emp
where sal>=1000
group by deptno
having (max(sal)+min(sal))/2<2500 and avg(sal) between 1200 and 2000;

 

-- job이 salesman이 아닌 사원 중에서 job별로 급여 합계가 5000이상인 직급, 급여합계를 검색
 -- 단, 급여 합계 내림정렬
select job '직급', sum(sal) '급여합계' from emp
where job<>'salesman' group by job having sum(sal)>=5000 order by '급여합계' desc;
  • select에서 as로 지어준 칼럼 별칭을 order by에서 사용했다.
  • job<>'salesman'은 job이 'salesman'이 아닌 경우라는 뜻이다.

 

 

2. distinct

더보기
  • 중복된 행을 제거한다.

 

select job from emp;
select distinct job from emp;
disitnct 사용 안 함
distinct 사용

 

select distinct job, deptno from emp;
  • 중복을 제거했지만 'manager'이면서 '10'인 것과 'manager'이면서 '20'인 것은 값이 다르기 때문에 출력된다.
결과값

 

 예제)

-- 부서별 직급을 정렬해서 출력
select distinct deptno '부서', job from emp order by deptno, job;
-- 부서별 직급 개수, 인원수 출력
select deptno '부서', concat(count(distinct job), '개') '직업 수', concat(count(*), '명') '사원'
from emp group by deptno;

 

 

3. 서브 쿼리

더보기
  1. 위치에 따른 서브쿼리 종류
    • 스칼라 서브쿼리: select절
    • 인라인 뷰: from절 / from (select ...) 논리적인 테이블
    • 중첩 서브쿼리: where, having절
  2. 상관(연관) 여부에 따른 서브쿼리 종류
    • 비상관(비연관) 서브쿼리: 서브쿼리와 메인쿼리가 상관없이 실행
    • 상관(연관) 서브쿼리: 메인쿼리와 서브쿼리가 관계를 맺음, 서브쿼리 내에 메인쿼리의 칼럼 존재

 

  • 처리 순서: 메인쿼리 -> 서브쿼리 -> 메인쿼리

 

 예제) 

-- jones가 근무하는 부서 이름 검색
select dname from dept where deptno=(select deptno from emp where ename='jones');
  • where에서 서브쿼리로 'jones'의 'deptno'를 검색(선택)하고 그것을 조건으로 사용했다.

 

 문제)

-- 평균급여보다 많이 받는 사원 검색
select ename, sal from emp where sal>(select avg(sal) from emp);
-- jones보다 급여를 많이 받는 사원 검색 / 단, 급여 내림차 순
select ename, sal from emp where sal>(select sal from emp where ename='jones')
order by sal desc;

 

 예제)

-- 10번 부서에서 근무하는 사원의 이름과 10번 부서의 부서명, 부서번호를 출력
select d.deptno 부서번호, d.dname 부서명, emp.ename '사원 명'
from (select deptno, dname from dept where deptno=10) d, emp order by ename;

select*from emp e, (select deptno, dname from dept where deptno=10) d where e.deptno=d.deptno;
-- 10번 부서와 20번 부서 사원 중에서 직급이 같은 사원들의 이름, 부서번호, 직급을 검색 
select e1.job, e1.deptno, e1.ename, e2.deptno, e2.ename
from (select ename, deptno, job from emp where deptno=10) e1,
	(select ename, deptno, job from emp where deptno=20) e2
where e1.job=e2.job;
-- 직급별로 직급, 최대급여를 출력하되, 최대 급여가 salseman의 최대급여보다 큰 그룹만 출력
select job, max(sal) maxsal from emp group by job
having max(sal)>(select max(sal) from emp where job='salesman');
-- blake와 같은 부서에 있는 사원 이름, 입사일 출력 / 단, 본인 제외
-- blake가 서로 다른 부서에 있을 수 있다.
select ename, hiredate
from emp
where deptno in(select deptno from emp where ename='blake') and ename<>'blake';
  • 'blake'가 동명이인으로 서로 다른 부서에 있을 수 있다는 것을 가정한 조건이 붙었다.
  • in을 통해 여러 조건 중 하나를 만족하면 조건에 충족하는 것으로 하고 서브쿼리를 통해 'blake'의 'deptno'를 검색/선택해왔다.

 

 예제) 

select (select dname from dept d where d.deptno = e.deptno) as dname, empno, ename
from emp e;

 

 

  • ~ all: 서브쿼리의 모든 결과에 대해 ~하다.
  • ~ any: 서브쿼리의 하나 이상의 결과에 대해 ~하다.
select ename, sal, deptno from emp
where deptno = any(select deptno from emp where sal>=3000);
  • where deptno in(select deptno from emp where sal>=3000); < 해당 코드와 두번째 코드가 동일하다.
  • in도 any도 괄호 안의 코드(값) 중 하나라도 만족하면 조건에 충족한다.

 

select ename, sal from emp
where sal>all(select sal from emp where deptno=30);
  • where sal>(select max(sal) from emp where deptno=30); < 해당 코드와 두번째 코드가 동일하다.

 

 

4. inner join

더보기
  • 두 개 이상의 테이블을 행끼리 결합하는 것
  • inner(내부) join: 양 쪽(테이블) 모두에 값이 있는 행(not null) 반환 / inner 생략 가능

 

-- 사원 이름, 호봉, 부서명 검색
select d.deptno, d.dname, e.ename, e.sal
from emp e join dept d on d.deptno=e.deptno
join salgrade s on e.sal between s.losal and s.hisal;
  • on에는 테이블을 합하는 join의 조건을 적는다.
  • 해당 코드에서는 dept를 emp에 합할 때, 동일하게 가지고 있는 열인 deptno를 이용하여 합한다.

 


 

전체 피드백

  • 밥 먹고 나서 집중력이 급격히 떨어지는 바람에 활용하는 부분에서 많이 헤맨 것 같다.
  • 초반에는 쉬웠는데 역시 갈수록 많이 어려워지는 것 같다. db랑 자바랑 연결할 때도 크게 헤맬 것 같은 기분이 든다.

 


728x90
728x90

 

수업내용 정리 (MySQL)

 

1. 복습문제

더보기
-- 급여가 1000~2000 사이가 아닌 사원
select*from emp where !(sal between 1000 and 2000);

-- 직급이 clerk, manager, analyst인 사원 검색
select*from emp where job in('clerk', 'manager', 'analyst');

-- 직급이 clerk, manager, analyst이 아닌 사원 검색
select*from emp where job not in('clerk', 'manager', 'analyst');

-- 급여가 2000이상이고 입사일이 1981-01-01 이후인 사원 검색
select*from emp where sal>=2000 and hiredate>='1981-01-01';
  • 직급은 [select distinct job from emp;] 코드를 통해 이름을 복사해서 작성했다.

 

 

2. Like 연산자

더보기
  • 와일드 문자
  • %: 0~n개의 문자를 가진 패턴
  • _: 1개의 문자를 가진 패턴 / 글자의 위치와 글자가 같아야 한다.

 

select 'HELLO' like 'hel%';	-- 참
select 'HELLO' like '__LLO';	-- 참
select 'HELLO' like 'HELLO_';	-- 거짓
select 'HELLO' like 'HELL_';	-- 참
  • 'HELLO'
  • 문자열의 앞에 'hel'이란 문자가 들어있는가: MySQL은 대소문자를 구분하지 않고, 대문자 'HEL'이 첫부분에 들어있기 때문에 반환 값은 1
  • 문자열의 세번째부터 마지막 글자까지 'LLO'인가: 위치와 문자가 동일하기 때문에 반환 값은 1
  • 문자열의 첫번째부터 다섯번째까지 'HELLO'이고, 마지막에 한 글자가 있는가(총 6글자인식): 'HELLO'는 들어있지만 마지막 문자가 없기 때문에 반환 값은 0
  • 문자열의 첫번째부터 네번째까지 'HELL'이고, 마지막 한 글자가 있는가(총 5글자로 인식): 'HELL'이 위치와 문자가 동일하고 마지막 문자가 있기 때문에 반환 값은 1

 

 예제)

-- 사원 이름이 'J'로 시작하는 사원 검색
select*from emp where ename like 'j%';
-- 사원 이름이 'R'로 끝나는 사원 검색
select*from emp where ename like '%r';
-- 사원 이름이 'R'을 포함하는 사원 검색
select*from emp where ename like '%r%';
-- 사원 이름 중 세번째 글자가 'A'인 사원 검색
select*from emp where ename like '__a%';
select*from emp where empno like '_7%';
select*from emp where hiredate like '1981%';
select*from emp where hiredate not like '1981%';

 

 문제) 1981년도에 입사한 사원 중에서 부서가 10번 또는 20번인 사원 검색

select*from emp where hiredate like '1981%' and (deptno=10 or deptno=20);
select*from emp where hiredate like '1981%' and deptno in(10,20);
  • 두 코드는 동일하지만 처음에 위에 버전으로 풀었다가 어제 배웠던 in이 생각나서 뒤늦게 추가했다.
  • in으로 코드를 짜는 것이 보기에도 좋고 타이핑하기도 편한 것 같다.

 

 

3. 숫자와 문자열 함수

 3-1) round / ceil / floor / truncate ㄱ 

더보기
  • round: 반올림
  • ceil: 올림
  • floor: 내림
  • truncate(n, m): n을 소수점 m자리까지 선택하고, 반올림은 안 한다.

 

select round(0.5), ceil(0.4), floor(0.6);
select round(3/2) as r_test;
select abs(1), abs(-1),abs(2-10);
  • round: 1 / ceil: 1 / floor: 0
  • as r_test는 as 뒤 문자로 칼럼명을 변경한 것이다. 작은 따옴표''를 사용하는 것이 원래 작성법이지만 안 사용해도 되는 경우가 있는데, 문자만 있거나 특수기호 언더바_ 하나를 사용하는 것 정도다. (공백은 안 된다.)

 

select truncate(12345.6789,-2);	-- 출력: 12300
  • -2를 넣었으므로 소수점이 아닌 양수에서 숫자를 떨궈, 12300이라는 값이 나온다.

 

 3-2) 최댓값, 최솟값 ㄱ 

더보기
select greatest(1,2,3);
  • 최댓값
  • 비교하고싶은 숫자를 greatest 괄호 안에 적으면 최댓값을 구해서 반환해준다.

 

select least(1,2,3,4,5);
  • 최솟값
  • 비교하고싶은 숫자를 least 괄호 안에 적으면 최솟값을 구해서 반환해준다.

 

 3-3) 제곱, 제곱근 함수 ㄱ 

더보기
  • pow(), power(): 구분없이 똑같은 함수

 

select pow(2,3), power(2,3), power(16,1/2), sqrt(16);
  • 순서대로 결과값이 8, 8, 4, 4가 나온다.
  • sqrt는 루트다.

 

 예제) 

-- 급여를 제곱하고 반올림
select sal, round(pow(sal,1/2)), round(sqrt(sal)) from emp;

 

 3-4) 문자열 연결 함수 ㄱ 

더보기
  • Oracle에서는 ||을 이용하여 문자를 연결할 수 있지만(ex: 'Hello'||2021||'bye'), MySQL에서는 안 된다.
  • concat: 괄호 안의 문자(숫자)들을 모두 더한다.
  • concat_ws: 괄호의 첫부분에 들어가는 문자를 괄호 안 문자(숫자)들을 더할 때 사이에 껴서 더해진다.

 

select concat('HELLO', ', ', 2021, ', ', 'BYE');
select concat_ws(' - ', 2020, 8, 4, 'AM');
select concat('E-NO: ', empno) empno, concat(ename, '님') ename, concat(sal,'원') sal from emp;
  • HELLO, 2021, BYE
  • 2020 - 8 - 4 -  AM
  • 칼럼에 따라 E-NO: (empno), (ename)님, (sal)원이 출력된다.

 

 문제) 칼럼 이름은 ename_job으로 하고, 출력은 (ename)_(job)으로 출력

select concat(ename," _ ", job) ENAME_JOB from emp;
select concat_ws(' _ ',ename, job) ENAME_JOB from emp;
  • concat, concat_ws 두 가지 방법 모두 사용하여 풀었다.
  • 칼럼 이름을 붙일 때에는 as (칼럼 명)으로 해야하지만 생략해도 된다. (초반엔 헷갈리니 추천하진 않음)

 

 3-5) 문자열 부분 추출 ㄱ 

더보기
  • substr: 전체 문자열에서 부분 문자열을 추출한다.
  • 자바에서 String.subString()과 동일하게 작동한다.
  • (문자, n): n번째부터의 문자 출력
  • (문자, n, m): n번째 문자부터 m번째 문자까지 출력

 

select substr('ABCDEFG',3), substr('ABCDEFG',3,2);
select substr('ABCDEFG',-4);
  • 순서대로 'CDEFG', 'CD', 'DEFG'가 출력된다.

 

 문제) 입사일이 2월인 사원 검색

-- 입사일이 2월
select hiredate, ename from emp where substr(hiredate,-5,2)=2;
  • 조건: (hiredate)의 -5번째 글자부터 -6까지의 글자가 02

 

 문제2) 입사일이 20일인 사원 검색

-- 입사일이 20일	/ like가 더 좋음
select hiredate, ename from emp where substr(hiredate,-2)=20;
select hiredate, ename from emp where hiredate like '%20';
  • 해당 상황에서는 like절을 쓰는 것이 편하고 좋으나 substr을 연습하는 겸 subser로 해보라고 하셔서 두 방법 모두 풀었다.
  • substr 조건: (hiredate)의 -2번째 글자부터 마지막 글자가 20
  • like 조건: 마지막 글자가 20

 

 3-6) left / right ㄱ 

더보기
select hiredate,
	left(hiredate, 4) as year,
	substr(hiredate,-5,2) as month,
	right(hiredate,2) as day
from emp;
  • left: 왼쪽부터 n번째 문자까지 (예문에서는 4번째)
  • right: 오른쪽부터 n번째 문자까지 (예문에서는 2번째)

 

 3-7) length ㄱ 

더보기
  • length: 바이트(byte)의 길이
  • char_lenght / charactor_length: 문자의 길이

 

select length('abcdef'), char_length('abcdef'), character_length('abcdef');
select length('ㄱㄴㄷㄹ'), char_length('ㄱㄴㄷㄹ'), character_length('ㄱㄴㄷㄹ');
  • 순서대로 6, 6, 6 출력
  • 순서대로 12, 4, 4 출력

 

 문제) 사원 이름(한글포함)이 4~6자인 사원 검색

select ename from emp where char_length(ename)>=4 and char_length(ename)<=6;
select ename from emp where char_length(ename) between 4 and 6;
  • 두 코드 모두 동일하게 돌아간다.
  • between을 사용하는 편이 간편하고 보기에도 좋다.

 

 3-8) trim ㄱ 

더보기
select concat('| ','hello',' |'),
	concat('| ',ltrim('       hello    '),' |'),
	concat('| ',rtrim('       hello    '),' |'),
	concat('| ',trim('       hello    '),' |');
  • trim: 양 쪽 공백을 없앤다.
  • ltrim: 왼쪽 공백을 없앤다.
  • rtrim: 오른쪽 공백을 없앤다.

 

 3-9) lpad / rpad ㄱ 

더보기
  • lpad(s,n,p): s가 n글자가 될 때까지 p를 왼쪽에 이어붙인다.
  • rpad(s,n,p): s가 n글자가 될 때까지 p를 오른쪽에 이어붙인다.

 

select lpad('abc',10,'-'), rpad('abc',5,'*');
  • 순서대로 '-------abc', 'abc**'가 출력된다.

 

 3-10) replace ㄱ 

더보기
  • replace(s, a, b): s 중 a를 b로 치환(변경)
  • 대소문자를 구분한다.

 

select replace('hello sql Hello','hello', 'bye');
  • 대소문자를 구분하기 때문에 'bye sql Hello'가 출력된다.

 

 

4. 날짜

 4-1) curdate, curtime, now ㄱ 

더보기
  • current_date / curdate: 현재 날짜 반환
  • current_time / curtime: 현재 시간 반환
  • current_timestamp / now: 현재 시간과 날짜 반환

 

select curdate(), curtime(), now();
출력 결과

 

 4-2) date, time, datetime ㄱ 

더보기
  • date: 문자열에 따라 날짜를 생성
  • time: 문자열에 따라 시간을 생성

 

select '2021-6-1' = '2021-06-01', date('2021-6-1') = date('2021-06-01');
select '1:2:3' = '01:02:03', time('1:2:3') = time('01:02:03');
select date('2021-6-1 1:2:3') = date('2021-6-1 01:02:05');
  • 형변환해준다고 생각하면 편하다.
  • 마지막 코드는 날짜로 변환했기 때문에 시간은 무시하고 날짜만 비교한다.

 

 예제) 

-- 1981-01-01부터 1981-12-31 사이에 입사한 사람
select*from emp where hiredate between '1981-1-1' and '1981-12-31';
select*from emp where hiredate between date('1981-1-1') and date('1981-12-31');
select*from emp where hiredate like '1981%';

 

 

  • datetime
  • year(datetime): 주어진 datetime 값의 년도 반환
  • monthname(datetime): 주어진 datetime 값의 월(영문) 반환
  • month(datetime): 주어진 datetime 값의 월 반환
  • weekday(datetime): 주어진 datetime 값의 요일값(0~7) 반환 / 월요일부터 0
  • dayname(datetime): 주어진 datetime 값의 요일명(영문) 반환
  • dayofmonth / day(datetime): 주어진 datetime 값의 날짜(일) 반
select hiredate,
	year(hiredate) as year,
	monthname(hiredate) as monthname,
	month(hiredate) as month,
	weekday(hiredate) as weekday,
	dayname(hiredate) as dayname,
	day(hiredate) as day
from emp;
결과값

 

-- 예시) 1981-12-03 --> 1981/12/3 THU
select hiredate, concat(concat_ws('/', year(hiredate), month(hiredate), day(hiredate)),
	'  ', upper(left(dayname(hiredate),3))) as hiredate2 from emp;
  • year, month, day를 통해 값을 추출하고, concat_ws를 이용해 사이마다 '/'를 넣었다.
  • 요일은 upper를 이용해서 대문자로 만들고 left로 3글자까지만 출력하도록 했다.
결과값

 

 4-3) 시간 ㄱ 

더보기
select concat_ws(' : ', hour(now()), minute(now()), second(now())) as time;
  • now를 통해 현재 시간의 시, 분, 초를 출력할 수 있다.
  • hour: 시간
  • munute: 분
  • second: 초

 

select adddate(now(), interval 1 day);	-- 날짜 더하기
select subdate(now(), interval 1 day);	-- 날짜 빼기
select hiredate, adddate(hiredate, interval 2 month) from emp;	-- 날짜 더하기
select hiredate, adddate(hiredate, interval -2 month) from emp;	-- 날짜 빼기
select hiredate, subdate(hiredate, interval 2 month) from emp;	-- 날짜 빼기
  • addDate / date_add(d, n): d에 n만큼 시간/날짜 더하기
  • subDate / date_sub(d, n): d에 n만큼 시간/날짜 빼기
  • add를 통해 날짜를 빼는 것도 가능하다.

 

select hiredate, now(), concat(abs(datediff(hiredate, now())), '일 경과') from emp;
select hiredate, now(), concat(datediff(now(), hiredate), '일 경과') from emp;
  • 위의 두 코드는 적은 날짜에서 큰 날짜를 빼도 절댓값을 구하는 공식으로 마이너스-가 안 나오게 하는 것과 그냥 큰 날짜를 앞에 두어 마이너스-가 안 나오게 하는 것의 차이일 뿐 동일한 코드다.
  • dateDiff(d, n): d에서 n만큼의 일수차
  • timeDiff(d, n): d에서 n만큼의 시간차

 

 예제) 

-- 입사일이 1981-12-05 기준 앞뒤로 5일 이내 사원 검색
select hiredate, ename, concat(abs(datediff(hiredate,'1981-12-05')), '일 경과') as '경과일'
		from emp where abs(datediff('1981-12-05', hiredate))<=5;

 

 4-4) 날짜/시간 형식 ㄱ 

더보기
select date_format(now(), '%y - %m - %d  %p %h시 %i분');
select date_format(now(), '%y-%m-%d %h:%i:%s');
  • 대소문자에 따라 다른 형식이 되기 때문에 대소문자를 구분한다.
  • %Y: 년도 4자리
  • %y: 년도 2자리
  • %M: 월 영문
  • %m: 월 숫자
  • %D: 일 영문(1st, 2nd ...)
  • %d / % e: 일 숫자
  • %T: 시간 (hh:mm:ss)
  • %r: 시간 (hh:mm:ss AM/PM)
  • %H / %k: 시 (24시)
  • %h / %l: 시 (12시)
  • %i: 분
  • %S / %s: 초
  • %p: AM/PM

 

-- str_to_date(S,F): s를 f형식으로 해석하여 시간/날짜로 변환
select str_to_date('2021-06-04 07:55:22', '%Y-%m-%d %T') as str_to_date;

 

 

5. 기타 함수

 5-1) if ㄱ 

더보기
select if(1>2, '1이 크다.', '2가 크다.');
  • if(조건, t, f): 조건이 참이라면 t, 아니라면 f 반환
  • 해당 코드는 참이 아니기 때문에 '2가 크다'가 출력된다.

 

 5-2) case ㄱ 

더보기
select
case
  when -1 > 0 then '-1은 양수다.'
  when -1 = 0 then '-1은 0이다.'
  else '-1은 음수다.'
end;
  • case 안에 when으로 조건을 주고 조건에 충족한다면 then에 반환할 값을 준다. 모든 when 조건에 충족하지 않으면 else의 값을 반환한다.
  • 해당 코드는 조건에 해당하는 것이 없기 때문에 else로 빠져서 '-1은 음수다'가 출력된다.

 

 예제) 

select
  sal,
  if (sal > 2000, 'Expensive', 'Cheap') as result1,
  case
    when sal < 1000 then '저급여'
    when sal between 1000 and 2000 then '일반급여'
    else '고급여'
  end as result2
from emp;
결과값

 

 5-3) ifnull, isnull ㄱ 

더보기
select ifnull('A', 'B'), ifnull(NULL, 'B');
select sal, comm, isnull(comm), sal*12+ifnull(comm,0) as annual from emp;
  • ifNull(a, b): a가 값이 있다면 a 출력, a가 null이면 b 출력
  • isNull(칼럼): 칼럼 값이 null이면 1, 아니면 0 출력
결과값_1
결과값_2

 


 

전체 피드백

  • 또 비공개로 올리고 말았다..

 


728x90
728x90

 

수업내용 정리 (MySQL)

 

0. SQL(구조적 질의어)

  1. DDL(데이터 정의어): create, alter, drop, (truncate/잘안씀) - 테이블, 계정, 뷰 등
  2. DQL(데이터 질의어): select ...
  3. DML(데이터 조작어): (select/빼는경우가 많음), insert, update, delete - 테이블 또는 뷰 데이터
  4. DCL(데이터 제어어): grant(권한부여), revoke(권한회수), commit(작업완료), rollback(작업취소)

 

 

1. Connection 추가

더보기
  • MySQL Workbench를 켰을때 중앙의 MySQL connections 바로 옆에 있는 + 버튼을 누른다.

 

  • Connection Name: Connection 이름 설정
  • Username: 해당 Connection을 사용할 유저 이름 설정(이미 있는 유저라면 해당 이름으로 작성)
  • Password: 새로운 유저라면 Store in Vault ... 을 눌러 비밀번호를 설정하고, 있는 유저라면 넘어간다.

 

  • 추가 완료!
  • 해당 Connection을 누르면 비밀번호를 입력한 후 들어갈 수 있다.

 

 

2. 계정

 2-1) 계정 생성 ㄱ 

더보기
  • 관리자 계정(root)에서 일반 계정 생성!

 

create user 계정이름 identified by '비밀번호';
create user 'icia' identified by '1234';
create user 'icia'@'%' identified by '1234';	-- 위의 코드와 동일
create user 'icia2'@'localhost' identified by '1234';
  • @'%': 내/외부 접속이 가능하다. 기본값이므로 생략이 가능하다.
  • @'localhost': 내부 접속만 가능하다.

 

 2-2) 비밀번호 변경 ㄱ 

더보기
alter user 'icia' identified by '1111';
  • icia 계정에 대한 비밀번호를 변경한다.

 

 2-3) 계정 삭제 ㄱ 

더보기
drop user 계정이름;
drop user 'icia2'; -- 삭제 불가
drop user 'icia2'@'localhost';
  • 계정 이름 뒤에는 기본값인 @'%'가 있기 때문에 @'localhost'로 만든 계정은 삭제할 때도 꼭 @'localhost'를 붙여야 삭제가 가능하다.

 

 2-4) 권한 설정 ㄱ 

더보기
grant all privileges on *.*to 'icia';	-- 모든 테이블에 관한 권한
grant all privileges on mydb.*to 'icia';	-- mydb 테이블에 관한 권한
  • *. : 모든 테이블
  • mydb. : mydb 테이블
  • grant all privileges on ~: ~에 관한 모든 권한을 설정

 

revoke all privileges on mydb.*from 'icia';	-- mydb 테이블에 관한 권한 회수
  • revoke all privileges on ~: ~에 관한 모든 권한을 회수

 

 

3. database/schemas 생성 (관리자/root 계정에서만 가능)

더보기
create schema mydb;
create database teamdb;
show databases;
  • 위 두 줄은 똑같이 database/schemas를 생성한 것이다.
  • 아래의 show databases는 생성한 database를 보여주는 코드다.

 

 

4. 테이블 (icia 계정으로 진행)

 4-1) 사용할 db 선택 ㄱ 

더보기
use mysql;	-- 권한 없어서 에러
use mydb;	-- 사용할 db 선택
  • 권한이 없는 것을 선택하면 에러가 나고 선택되지 않는다.

 

 4-2) 테이블 생성 ㄱ 

더보기
drop table if exists dept;
  • 생성하기 전에 선택한 db에 dept라는 테이블이 있다면 삭제한다.

 

create table dept(
	deptno tinyint unsigned,
	dname varchar(10),
	loc varchar(10),
	constraint pk_dept primary key(deptno));
  • deptno, dname, loc: 칼럼명을 설정한 것이다.
  • tinyint, varchar: 타입인데 아직 배우지 않았다.
  • primary key: 해당 테이블의 기본적인 값. 다른 항목과 중복값을 가질 수 없고, null 값을 가질 수 없다. 보통 테이블의 첫 칼럼이 pk에 배치된다. 테이블의 대표값이 아님!

 

 

create table emp(
	empno INT,  -- 사원번호
	ename VARCHAR(10),   -- 사원이름
	job VARCHAR(9),      -- 직급
	mgr INT,             -- 상관번호
	hiredate DATE,       -- 입사일
	sal INT,  -- 급여
	comm INT,            -- 보너스
	deptno tinyint unsigned, -- references DEPT(DEPTNO), 소속부서번호
    CONSTRAINT pk_emp PRIMARY KEY(empno), 
    CONSTRAINT fk_deptno foreign key(deptno) references dept(deptno)
 );
drop table if exists salgrade;
create table salgrade(
	grade tinyint primary key, -- _-128
    losal int,
    hisal int);
  • 사원, 급여 테이블 추가

 

 4-3) 테이블 내 검색 ㄱ 

더보기
select deptno, dname, loc from dept;
select * from dept;
  • select (검색할 칼럼명) from (검색할 db);
  • 검색할 칼럼명에 *(별표/애스터리스크)을 작성 시 모든 칼럼이 표시된다.

 

select ename, sal, 1, 'Hello', null from emp;
  • 원하는 칼럼(열)만 선택해서 검색
  • 1, 'Hello'는 없는 칼럼이므로 그냥 옆에 추가된 상태로 보인다.

 

select * from emp
where deptno=30;
  • 원하는 row(행)만 골라서 검색
  • where에 조건을 적는다.

 

select * from emp
order by empno; -- order by절 정렬기준(오름차)
-- order by empno desc; -- order by절 정렬기준(내림차)
  • 원하는 순서대로 데이터 검색

 

select*from emp limit 5;
select*from emp limit 0,5;	-- 0부터 5개까지	-- 페이징 1,2,3,4,5
select*from emp limit 5,5;	-- 5부터 5개까지
  • 원하는 만큼 데이터 가져오기
  • limit (시작인덱스), (가져올 개수)

 

 4-4) 데이터 추가(삽입) ㄱ 

더보기
insert into dept(deptno, dname, loc) values(10, 'accounting', 'NEW YORK');
insert into dept values(20, 'research', 'DALLAS');
insert into dept values(30, 'sales', 'CHICAGO');
insert into dept values(40, 'operations', 'BOSTON');
  • insert into (db(칼럼)) values(값);
  • 여러줄을 실행할 때에는 드래그해서 윗쪽에 번개모양을 누르면 된다.

 

INSERT INTO emp VALUES(7369,'SMITH','CLERK',7902,'1980-12-17',800,NULL,20);
INSERT INTO emp VALUES(7499,'ALLEN','SALESMAN',7698,'1981-2-20',1600,300,30);
INSERT INTO emp VALUES(7521,'WARD','SALESMAN',7698,'1981-2-22',1250,500,30);
INSERT INTO emp VALUES(7566,'JONES','MANAGER',7839,'1981-2-4',2975,NULL,20);
INSERT INTO emp VALUES(7654,'MARTIN','SALESMAN',7698,'1981-9-28',1250,1400,30);
INSERT INTO emp VALUES(7698,'BLAKE','MANAGER',7839,'1981-5-1',2850,NULL,30);
INSERT INTO emp VALUES(7782,'CLARK','MANAGER',7839,'1981-9-6',2450,NULL,10);
INSERT INTO emp VALUES(7839,'KING','PRESIDENT',NULL,'1981-11-17',5000,NULL,10);
INSERT INTO emp VALUES(7844,'TURNER','SALESMAN',7698,'1981-9-8',1500,0,30);
INSERT INTO emp VALUES(7900,'JAMES','CLERK',7698,'1981-3-12',950,NULL,30);
INSERT INTO emp VALUES(7902,'FORD','ANALYST',7566,'1981-12-3',3000,NULL,20);
INSERT INTO emp VALUES(7934,'MILLER','CLERK',7782,'1982-1-23',1300,NULL,10);
insert into salgrade values (1,700,1200);
insert into salgrade values (2,1201,1400);
insert into salgrade values (3,1401,2000);
insert into salgrade values (4,2001,3000);
insert into salgrade values (1,3001,9999);
  • 사원, 급여 테이블에 데이터 추가

 

 

5. 사칙연산

더보기
  • 더하기(+), 빼기(-), 곱하기(*), 나누기(/)는 그대로 사용한다.

 

select mod(10,3);
  • 나머지
  • MySQL에서는 %를 쓸 수 있지만 Oracle에서는 사용할 수 없기 때문에 mod를 사용한다.

 

select 5-2.5 from dual;
  • MySQL에서는 뒤의 from dual을 생략해도 되지만 Oracle에서는 안 된다.

 

select 'ABC' + 3;		-- 3
select '1' + '002';		-- 3
  • 문자열에 사칙연산을 하면 0으로 인식하지만, 문자열인데 숫자만 있을 경우엔 알아서 숫자로 인식한다.

 

select true, false;			-- 1, 0
select !true, not 1, !false, not 0;	-- 0, 0, 1, 1
  • true: 1
  • false: 0
select true is true, true is not true;	-- true는 true다, true는 false다
select true = true, true != true;	-- true는 true다, true는 false다
  • is연산자: ==       null 값 비교일 경우 사용한다.
  • is not 연산자: !=

 

-- 부서번호가 30이면서 급여가 2000 이상인 사원 검색
select*from emp where deptno = 30 and sal >= 2000;
-- 전체사원중에서 급여가 1000에서 2000인 사원
select*from emp where sal >= 1000 and sal <= 2000;
-- 부서번호가 10 또는 20
select*from emp where deptno = 10 or deptno=20;
  • 논리연산자
  • &&, and: 논리곱 (모두 해당하는 경우)
  • ||, or: 논리합 (하나라도 해당하는 경우)
select*from emp where sal between 1000 and 2000;
select*from emp where deptno in(10,20);
  • between: between a and b / a에서 b 사이의 값 and 대응
  • in: in(a,b) / a 또는 b의 값 or 대응

 

 ex ㄱ 

더보기
-- 사원번호가 홀수인 사원의 사원번호, 사원이름, 직급 검색
select empno,job,ename from emp
where mod(empno,2)=1;

-- 커미션이 null인 사원, null이 아닌 사원
select ename, comm from emp
where comm is null;
select ename, comm from emp
where comm is true;		-- is not null

-- 부서번호가 20번인 사원
select * from emp where deptno=20;
-- 부서번호가 20번이 아닌 사원
select * from emp
-- where !(deptno = 20);
-- where not(deptno != 20);
-- where deptno != 20;
where deptno <> 20;

 

 

 

 


 

질문한 내용이나 어려웠던 점 메모

1. 단축키

  • 자바를 하다가 와서 그런지 한 줄 삭제를 하려고 ctrl+D를 눌러서 선택된 줄(혹은 드래그한것) 복사 단축키를 알게 되었다..자꾸 복사하고 있어서 ctrl+Z를 계속 누르고 있었다.

 


 

전체 피드백

  • 오늘 배운 것은 비교적 간단한 것들이라 그렇게 어렵지만은 않았다!
  • MySQL을 하고 다시 Java로 돌아갈 것이라고 하셨다(Java에서 하던 PhoneBook이라던가 MySQL에 연동하는 식). 그전에 잊지 않도록 짬나는 시간에 복습하는거 잊지 말기!

 


 

 + 카테고리 설정 잊지 말기 ㅠ

728x90
728x90

 

수업내용 정리 (Java)

 

1. Stream (데이터의 흐름)

 예제 ㄱ 

더보기
FileInputStream fis = null;
  • 파일을 읽어오기에 앞서 선언해둔 stream에 null값을 넣지 않으면 close() 메소드를 사용할 때 오류가 난다.
  • 이해가 안 가면 외우기..!

 

try {
	fis = new FileInputStream("input.txt");
	int i;
	while((i=fis.read()) != -1) {
		System.out.print((char)i);
	}
	System.out.println();
}
  • i는 fis.read()값을 가지고, i가 -1이 아닐 때 while문을 돌려 파일을 읽어온다.

 

 catch (FileNotFoundException e) {
	System.out.println("FileInputException 예외 발생");
	e.printStackTrace();	// 위치 추적
}
  • 해당 코드는 오류가 난다.
  • 위의 fis.read()의 예외처리를 하지 않았기 때문인데, 이것을 해결하기 위해서 catch를 하나 더 만들어도 되지만 러프하게 처리해도 되는 경우에는 이미 만들어둔 catch의 FileNotFoundException을 Exception으로 바꾸면 해결이 된다. ( Exception이 FileNotFoundException의 조상타입이라 가능한 방법이다.)
  • 밑에 고친 코드를 올려놓았다.
// 고친 코드
 catch (Exception e) {
	System.out.println("Exception 예외 발생");
	e.printStackTrace();	// 위치 추적
}

 

finally {
	try {
		fis.close();
	} catch (IOException e) {
		System.out.println(e);	// 원칙: e.getMessage()
		e.printStackTrace();
	}
}
System.out.println("continue");
  • 코드가 try에서 멈추든, catch에서 멈추든 무조건 실행되는 구간, finally
  • fis.close()를 넣고, 마찬가지로 실행되지 않을 수 있기 때문에 예외처리를 해준다.
더보기
char ch1='A'; char ch2='B';
Writer out=new FileWriter("hyper.txt");
out.write(ch1);
out.write(ch2);
out.close();
  • char 변수에 각 각 A, B를 담아 두 개 선언한다. (유니코드를 사용하기 때문에 2byte씩 가지고 있다.)
  • FileWriter을 통해 파일을 생성한다.
  • 파일 안에 적을 내용을 write(스트림)를 통해 전송한다.
  • 할 일이 끝났다면 close를 통해 닫아준다.
  • 해당 클래스가 들어있는 자바 패키지 파일을 보면 이 텍스트 파일이 생겨난 것을 확인할 수 있다.
더보기
  • 개행 뜻: 강제 줄 바꿈
  • 개행은 newLine 메소드의 호출을 통해서 이뤄진다. 이렇듯 \n이 아닌 newLine 메소드 호출을 통해서 개행을 구분하는 이유는 시스템에 따라서 개행을 표현하는 방법이 다르기 때문이다.

 

// 문자열 출력을 위한 스트림의 구성
BufferedWriter out = new BufferedWriter(new FileWriter("String.txt"));
out.write("박지성 - 메시 멈추게 하는데 집중하겠다.");
out.newLine();
out.write("팀이 승리하는 것을 돕기 위해 최선을 다하겠다.");
out.newLine();
out.write("환상적인 결승전이 될 것이다.");
out.newLine();
out.write("기사 제보 및 보도자료");
out.newLine();
out.write("press@goodnews.co.kr");
out.close();
System.out.println("기사 입력 완료.");
  • 빠른 출력을 위해 BufferedWriter을 사용 (필터)
  • newLine()으로 줄바꿈
  • 쓰기가 끝났다면 close를 통해 닫아준다.

 

// 문자열 입력을 위한 스트림의 구성
BufferedReader in = new BufferedReader(new FileReader("String.txt"));
String str;
while (true) {
	str = in.readLine();
	if (str == null)
		break;
	System.out.println(str);
}
in.close();
  • 빠른 읽기를 위해 BufferedReader을 사용 (필터)
  • readLine() 호출 시 개행 정보는 문자열의 구분자로 사용되고 버려지므로, 문자열 출력 후 개행을 위해서는 println을 사용해야 한다.
  • 읽기가 끝났다면 close를 통해 닫아준다.
더보기
File file = new File("C:\\myJava\\java");

 

if(file.exists() == false) {
  • file.exists() == false는 file이 없다는 뜻이다.
  • isDirectory() == ture는 file이 폴더라면 이라는 뜻이다.
//	file.mkdir();	// 최하위 폴더 생성(중요!!)
	file.mkdirs();	// 상위폴더까지 생성
	System.out.println("존재하지 않습니다. 폴더를 생성합니다.");
}
  • mkdir()은 최하위 폴더만 생성하고, mkdirs()는 상위 폴더까지 생성한다.

 

 

2. 람다 (가볍게!) (참고)

 간단 설명 ㄱ 

더보기
  • 익명 함수
  • 장점
    1. 코드의 간결성: 복잡한 코드를 극단적으로 줄일 수 있다.
    2. 지연연산 수행: 지연연상을 수행함으로 불필요한 연산을 최소화할 수 있다. (아직 모르겠음!)
    3. 병렬처리 가능: 멀티스레드를 사용하여 병렬처리를 할 수 있다.
  • 단점
    1. 람다를 사용하면서 만든 무명함수는 1회성으로, 재사용이 불가능하다.
    2. 람다식의 호출이 까다롭다.
    3. 람다를 남발하면 오히려 가독성이 떨어져 코드가 지저분해질 수 있다.
  • 함수형 인터페이스: 추상 메소드가 오직 1개여야만 한다.

 

 예제 ㄱ 

더보기
package ex1;

@FunctionalInterface
interface Add{
	public int add(int x, int y);
}

public class LambdaTest1 {
	public static void main(String[] args) {
		Add addInst = (x, y) -> {System.out.print(x+"+"+y+"="); return x+y;};
		
		System.out.println(addInst.add(1,2));
	}
}

 

 

@FunctionalInterface
interface Add{
	public int add(int x, int y);
}
  • 한 클래스 내에서 퍼블릭 클래스 위나 아래에 인터페이스를 하나 생성하고, 추상 메소드를 하나 만든다.
  • 인터페이스 위의 @FunctionalInterface는 함수형 인터페이스에 메소드가 하나인지 하나이상인지 검사해준다.

 

public class LambdaTest1 {
	public static void main(String[] args) {
		Add addInst = (x, y) -> {System.out.print(x+"+"+y+"="); return x+y;};
		//Add addInst = (x, y) -> {return x+y;};
		//Add addInst = (x, y) -> x+y;
		
		System.out.println(addInst.add(1,2));
	}
}
  • 해당 코드는 람다식을 이용하여 인터페이스를 구현한 코드다.
  • (x, y)는 매개변수, 중괄호{} 안에 있는 코드는 실행할 코드다.
  • 실행코드가 두 문장 이상이거나 return이 들어가 있다면 중괄호{}를 써줘야 한다. 만약, 실행 코드가 한 문장이고, return도 없다면 중괄호{} 없이 작성해도 된다.

 

// 1
new Add() {
	@Override
	public int add(int x, int y) {
		return x+y;
	}
};
//2
Add addInst = new Add() {
	public int add(int x, int y) {
		return x+y;
	}
};
  • 1, 2 모두 위의 람다식과 같은 코드
더보기
package ex3;

public class LambdaTest2 {
	public static void main(String[] args) {
		MyNumber mN = (x, y) -> x>y ? x:y;
		System.out.println("Max="+mN.getMax(10,20));
	}
}

@FunctionalInterface
interface MyNumber {
	public int getMax(int x, int y);
}
  • 해당 코드는 삼항연산자를 이용해 람다식으로 두 수 중 최대값을 반환하는 것을 구현한 코드다.
  • (x, y) ⬅️ 매개변수
  • x>y ? x:y ⬅️ 실행코드 (삼항연산자)

 


 

질문한 내용이나 어려웠던 점 메모

 - 오늘 내용 전부 ㅠㅠ..

 


 

전체 피드백

  • 람다가 익숙해진다면 정말 코드를 짜는데 드는 시간이 줄어들 것 같지만, 람다를 이해하는 것은 제치고 머리에 집어넣는 것만으로도 오래 걸릴 것 같다는 생각이 들었다. 화이팅..

 


 

 + 최근 퇴실요정이 생겨서 퇴실을 잊지 않게 되었다!

 ++ 오늘은 일지도 공개로 제대로 올림!

728x90
728x90

 

수업내용 정리 (Java)

 

1. HashMap

더보기
public class HashMapMain {
	public static void main(String[] args) {
		HashMapList mList = new HashMapList();
		Member lee = new Member(1001, "이순신");
		Member kim = new Member(1002, "김유신");
		Member kang = new Member(1003, "강감찬");
		Member hong = new Member(1004, "홍길동");
		Member hong2 = new Member(1004, "홍길동");
		Member hong3 = new Member(2008, "홍길동");
		
		mList.addMember(lee);
		mList.addMember(kim);
		mList.addMember(kang);
		mList.addMember(hong);
		mList.addMember(hong2);
		mList.addMember(hong3);
		
		mList.showAllMember();
		
		mList.removeMember(lee.getId());
		
		mList.showAllMember();
		
		
		HashMap<Integer, String> hMap = new HashMap<>();
		hMap.put(1001, "kim");
		hMap.put(1002, "kim");
		hMap.put(1003, "park");
		hMap.put(1004, "hong");
		System.out.println(hMap);
	}
}
  • HashMap을 이용한 멤버 목록

 

 

public class Member {
	private int id;
	private String name;
	
	public Member(int id, String name) {
		this.id = id;
		this.name = name;
	}

	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	@Override
	public String toString() {
		return id+"\t"+name;
	}
}
  • Member 클래스는 어제자 예제와 동일하다.

 

 

public class HashMapList
// 필드
private HashMap<Integer, Member> hashMap;
  • Map <K, V>에 따라 필드를 저장한다.

 

// 생성자
public HashMapList() {
	this.hashMap = new HashMap<>();
}

 

public void addMember(Member member) {
	// 1001, new Member(1001,"강감찬")
	// 1002, new Member(1002,"홍길동")
	this.hashMap.put(member.getId(), member);
}
  • 매개변수로 Member 타입으로 저장할 member를 받아온다.
  • k 값에 member의 id를 넣고, v 값에 member 변수를 넣는다.

 

public boolean removeMember(int memberId) {
	if (hashMap.containsKey(memberId)) {
		hashMap.remove(memberId);
		return true;
	}
	System.out.println(" > 정보를 찾을 수 없습니다.");
	return false;
}
  • 매개변수로 삭제할 memberId를 받아와서 Map 내부에 해당하는 key가 있으면 true 값을 반환하고, 아니라면 false 값을 반환한다.

 

public void showAllMember() {
	Collection<Member> mList = hashMap.values();
//	System.out.println(mList);
	for(Member mb:mList) {
		System.out.println(mb); //Member toString
	}
	System.out.println("---------------");

}
  • HashMap에서 반복문 구현
  • Member 타입의 임시변수 mList에 v값을 저장한다.
  • foreach를 돌려 새로운 임시변수에 mList의 값을 하나씩 가져와 출력한다.
  • 주석처리 된 System.out.println(mList); 라고 출력해도 되지만, 가로로 쭉 출력되는 것이 보기에 좋지 않다. (비추!)
public void showAllMember2() {	
	Iterator<Integer> ir = hashMap.keySet().iterator();
	while(ir.hasNext()) {
		int key = ir.next();
		Member m = hashMap.get(key);
		System.out.println(m);
	}
	System.out.println("---------------");
}
  • Iterator을 이용한 멤버 전체 출력
  • ir 값에 k값을 집어넣고, while문의 조건에 ir.hasNext를 넣어 Map의 다음 값이 있다면 true, 없다면 false를 입력받아 반복문을 돌린다.
  • 임시변수에 ir.next를 통해 현재 값을 저장한다.
  • Member 임시변수에 k값에 해당하는 v값을 저장하고, 출력한다.

 

 

2. 파일 입출력 스트림 (맛보기.....)

더보기
  • 자바 스트림의 큰 분류: 입력 스트림(프로그램으로 데이터를 읽어들이는 스트림), 출력 스트림(프로그램으로부터 데이터를 내보내는 스트림)
  • 데이터의 입력을 위해서는 입력 스트림을, 출력을 위해서는 출력 스트림을 형성해야한다. (스트림은 인스턴스의 생성을 통해 형성된다.)

 

  • 파일 기반의 입력 스트림 형성
    • 파일 run.exe(예시) 대상의 입력 스트림 생성(인스턴스 생성)
    • FileInputStream 클래스는 InputStream 클래스를 상속한다.
  • InputStream 클래스: 바이트 단위로 데이터를 읽는 모든 입력 스트림 클래스의 최상위 클래스 (파일에 맞춰서 read 메소드 구현)
  • OutputStream 클래스: 바이트 단위로 데이터를 쓰는 모든 출력 스트림 클래스의 최상위 클래스
  • GDInputStream 클래스: 존재하지 않는 가상의 클래스 (장치에 맞춰서 read 메소드 구현)

 

  • InputStream 클래스(추상화 클래스)의 대표적인 두 메소드
    • public abstract int read() throws IOException
    • public void close() throws IOException
  • 입력의 대상에 적절하게 read 메소드가 정의되어 있다. 그리고 입력 대상에 따라서 입력 스트림을 의미하는 별도의 클래스가 정의되어있다.

 

// 파일 대상의 입력 스트림 생성
InputStream in = new FileInputStream("run.exe");
int bData = in.read();
  • 오버라이딩에 의해 FileInputStream의 read 메소드 호출

 

  • 파일 대상의 출력 스트림 형성(입출력 스트림은 대부분 쌍(pair)을 이룬다.

InputStream <-> OutputStream

FileInputStream <-> FileOutputStream

 

 

public class Ex01 {
	public static void main(String[] args) throws IOException {
		InputStream in = new FileInputStream("boss.mp4");
		OutputStream out = new FileOutputStream("bossCopy.mp4"); // 자동으로 생성된다.
		long start = System.currentTimeMillis();
		
		int copyByte = 0;
		int bData;
		while (true) {
			bData = in.read();	// 1바이트 씩 읽기
			if (bData == -1)
				break;
			out.write(bData);
			copyByte++;
		}
		in.close();
		out.close();
		// 40.199초
		
		long end = System.currentTimeMillis();
		System.out.println("파일복사 시간: "+(end-start)/1000.+"초");
		System.out.println("복사된 바이트 크기 " + copyByte);
	}
}
  • InputStream in에 new FileInputStream()으로 읽어들일 파일(자바 소스와 같은 폴더에 들어있어야 함!)의 이름을 큰따옴표"" 안에 적는다.
  • OutputStream out에 새로 생성할 파일의 이름을 적는다.
  • copyByte라는 변수를 만들어 값을 0으로 설정하고, bData라는 변수도 선언해둔다. (변수명은 달라도 상관없다.)
  • while문 조건을 true로 두고 bData에 in.read();를 통해 읽어들인 바이트 값을 저장한다. (1바이트씩 읽는다.)
  • 만약 bData에 -1 값이 들어갔다면 break를 통해 while문을 종료한다.
  • 조건에 충족하지 않았다면 out.write();를 통해 bData 값 만큼 출력하고, copyByte를 1씩 올린다.
  • in/out 코드 모두 close() 메소드를 통해 닫아준다.
  • long start/end는 시간을 재기 위한 코드 (컴퓨터마다 차이는 있겠지만 내 노트북으로는 해당 코드로 16GB 영상을 복사하는데 40.199초가 나왔다.)

 

InputStream in = new FileInputStream("boss.mp4");
		OutputStream out = new FileOutputStream("bossCopy.mp4");
		long start = System.currentTimeMillis();
		
		int copyByte=0;
		int readLen;
		byte buf[]=new byte[1024];
		while(true)
		{
			readLen=in.read(buf);
			if(readLen==-1)
				break;
			out.write(buf, 0, readLen);
			copyByte+=readLen;
		}
		// 0.057초
		
		long end = System.currentTimeMillis();
		System.out.println("파일복사 시간: "+(end-start)/1000.+"초");
		System.out.println("복사된 바이트 크기 " + copyByte);
  • 위의 코드에서 start/end 사이의 내용만 바꾼 코드
  • 전체 구조는 비슷하지만 readLen이란 변수에 in.read만큼 읽어들일때, buf를 통해 바이트[1024] 값을 담아 1024배 빠르게 읽어들일 수 있도록 한다. (이론상으로는 1024배만큼 빨라져야 한다.)
  • 위의 코드가 계단을 통해 위로 올라가는 것이었다면 이 코드는 엘레베이터를 통해 위로 올라가는 느낌
  • out.write에는 buf 배열 0번째 인덱스부터 readLen 바이트를 저장한다.
  • copyByte는 readLen 값을 누적해서 저장한다.
  • long start/end는 시간을 재기 위한 코드 (컴퓨터마다 차이는 있겠지만 내 노트북으로는 해당 코드로 16GB 영상을 복사하는데 0.057초가 나왔다.) (같은 영상인데 훨씬 빠르다!)

 


 

질문한 내용이나 어려웠던 점 메모

1. 입출력 스트림

  • 아주 조금만 배웠는데도 너무 어렵다..우선 외워두기만 하고 이해하는 것은 나중에 하기로 했다. (실상 외우기도 힘들 것 같다 ㅠㅠ )

2. 필터

  • 정리할 만큼의 이해도 되지 않아서 다시 찾아보고 해야할 것 같다.

 


 

전체 피드백

  • 이전에 배운걸 전부 이해하지 못한 상태에서 새로운걸 넣으려고 해서 그런지 더 들어오지 않는 기분이 들었다. 학원이 끝나고 일지를 쓰면서 다시 독해도 하고 그러면서 조금씩 이해도가 높아지고는 있지만 주말에 더 시간을 써서 공부를 해야할 것 같다.
  • 날씨에 컨디션이 영향받지 않도록 하기!
  • 일지를 비공개로 올리지 않도록 노력하기..(그리고 늦지 않게 쓰도록 노력하기..!)

 


728x90
1 ··· 4 5 6 7 8 9 10 ··· 27