일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- react
- CSS
- 정보처리기사실기요약
- javascript
- php
- 국비코딩
- spring
- 자바스크립트
- Java의정석
- VUE
- Oracle
- 리액트네이티브
- 오라클
- 타입스크립트
- 정보처리기사실기정리
- 국비IT
- ReactNative
- 자바스크립트 코딩테스트
- 코딩테스트
- 자스코테
- 자바의정석
- 리액트
- typescript
- 정보처리기사정리
- 정보처리기사
- 이안의평일코딩
- 평일코딩
- 정보처리기사요약
- 정보처리기사실기
- 스프링
- Today
- Total
이안의 평일코딩
Oracle 19일차 - 서브쿼리 본문
2020.11.10(화)
서브쿼리, PL/SQL (Procedure, Function, Trigger) : MongoDB
1. 서브쿼리
= 조인 => 여러개의 테이블에서 필요한 데이터 모아서 수집
단점 : SELECT에서만 사용 가능
= 서브쿼리 => 여러개의 SQL문장을 한개로 통합
DML 전체에서 사용이 가능
= 종류
1) 단일행 서브쿼리 : 서브쿼리의 결과값이 1개
2) 다중행 서브쿼리 : 서브쿼리의 결과가 여러개
3) 인라인 뷰 : FROM (SELECT~)
4) 스칼라 서브쿼리 : 컬럼대신 사용
SELECT empno,ename,(SELECT ~) as dname
단일행
1
2
3
|
SELECT * FROM emp ====> 메인쿼리
WHERE deptno=(SELECT ~) ====> 서브쿼리
서브쿼리에서 실행된 결과를 메인쿼리가 받아서 처리
|
cs |
예) emp테이블 => 사원의 평균급여 => 평균보다 적게 받는 사원 정보를 출력
*하기 코드는 오류 : 단일행과 그룹행을 섞을 수 없음
1
|
SELECT * FROM emp WHERE sal<AVG(sal);
|
cs |
단일행 2개
1
2
|
SELECT AVG(sal) FROM emp;
SELECT * FROM emp WHERE sal<2073;
|
cs |
서브쿼리는 ( )안에
1
|
SELECT * FROM emp WHERE sal<(SELECT AVG(sal) FROM emp);
|
cs |
예2) SCOTT => scott가 근무하는 부서에 같이 근무하는 사원의 모든 정보 출력
단일행 2개
1
2
|
SELECT deptno FROM emp WHERE ename='SCOTT';
SELECT * FROM emp WHERE deptno=20;
|
cs |
서브쿼리로 하나로 줄임!
1
|
SELECT * FROM emp WHERE deptno=(SELECT deptno FROM emp WHERE ename='SCOTT');
|
cs |
* 단일행은 반드시 서브쿼리의 결과값 1개
단일행 서브쿼리의 연산자
=> 비교연산자 (= , !=(<>) , <= , >= , < , >)
-- DISTINCT (중복제거)
1
2
|
SELECT * FROM emp WHERE deptno=(SELECT DISTINCT deptno FROM emp);
SELECT DISTINCT deptno FROM emp;
|
cs |
-- GROUP BY
-- 사원의 평균 급여 보다 높은 부서의 부서번호, 인원수를 출력
1
|
SELECT deptno, COUNT(*) FROM emp GROUP BY deptno HAVING AVG(sal)<(SELECT AVG(sag) FROM emp);
|
cs |
-- 스칼라 서브쿼리 => 결과값이 한개(컬럼)
1
2
3
|
SELECT empno, ename, job, dname, loc
FROM emp, dept
WHERE emp.deptno=dept.deptno;
|
cs |
예3) 단일행2개 as로 컬럼명을 바꿔준다 dname, loc으로
1
2
3
|
SELECT empno,ename,job,(SELECT dname FROM dept d WHERE d.deptno=e.deptno) as dname,
(SELECT loc FROM dept d WHERE d.deptno=e.deptno) as loc FROM emp e;
SELECT empno,ename,job,sal,grade FROM emp, salgrade WHERE sal BETWEEN losal AND hisal;
|
cs |
=> 서브쿼리
1
2
3
|
SELECT empno,ename,job,sal,
(SELECT grade FROM salgrade WHERE sal BETWEEN losal AND hisal) as grade
FROM emp;
|
cs |
예4) 사원 정보 : 사번, 이름, 직위, 입사일, 부서명, 근무지, 급여등급 ==> KING사원과 같은 부서의 사원 출력
1
2
3
4
5
6
|
SELECT empno, ename, job, hiredate,
(SELECT dname FROM dept d WHERE d.deptno=e.deptno) as dname,
(SELECT loc FROM dept d WHERE d.deptno=e.deptno) as loc,
(SELECT grade FROM salgrade WHERE sal BETWEEN losal AND hisal) as grade
FROM emp e
WHERE deptno=(SELECT deptno FROM emp WHERE ename='KING');
|
cs |
-- 다중형 서브쿼리
데이터가 여러개인 경우
= 데이터 전체를 처리 ==> IN
1
2
3
|
SELECT empno,ename,job,deptno
FROM emp
WHERE deptno IN(SELECT DISTINCT deptno FROM emp);
|
cs |
= 최대값 => ALL, MAX()
= 최소값 => ANY, MIN()
=> >ANY() => 수행된 결과중에 최소값 >ANY(SELECT deptno FROM dept) ANY(10,20,30,40,50) => 10
(SELECT MIN(deptno)_FROM dept)
(SELECT MAX(deptno)_FROM dept)
<ANY() => 수행된 결과중에 최대값 >ANY(SELECT deptno FROM dept) ANY(10,20,30,40,50) => 50
>ALL() => 수행된 결과중에 최대값 >ALL(SELECT deptno FROM dept) ANY(10,20,30,40,50) => 50
<ALL() => 수행된 결과중에 최소값 >ALL(SELECT deptno FROM dept) ANY(10,20,30,40,50) => 10
>ANY 최소값보다 큰 deptno애들만 불러옴 deptno = 20, 30
<ANY 최대값보다 작은 deptno애들만 불러옴 deptno = 10, 20
1
2
3
4
5
6
7
|
SELECT empno,ename,job,deptno
FROM emp
WHERE deptno>ANY(SELECT DISTINCT deptno FROM emp); --최소값 (10,20,30) => 10
SELECT empno,ename,job,deptno
FROM emp
WHERE deptno<ANY(SELECT DISTINCT deptno FROM emp); --최대값 (10,20,30) => 30
|
cs |
ALL 출력안됨
1
2
3
4
5
6
7
|
SELECT empno,ename,job,deptno
FROM emp
WHERE deptno<ALL(SELECT DISTINCT deptno FROM emp); --최소값 (10,20,30) => 30
SELECT empno,ename,job,deptno
FROM emp
WHERE deptno>ALL(SELECT DISTINCT deptno FROM emp); --최대값 (10,20,30) => 10
|
cs |
ANY는 IN과 같이 OR로 하나라도 만족하면 값을 불러오지만
ALL은 AND로 모든 값이 조건을 충족해야 값을 불러옴!
-- 인라인뷰, TOP-N(rownum) => 중간에 데이터를 자를 수 없다
중간에 데이터 자르면 출력 안됨
1
2
|
SELECT ename,job,sal,rownum FROM emp
WHERE rownum BETWEEN 5 AND 10;
|
cs |
==> 인라인뷰 페이징기법
1
2
3
4
|
SELECT ename,job,sal,rownum
FROM (SELECT ename,job,sal,rownum as num
FROM (SELECT ename,job,sal FROM emp ORDER BY sal DESC))
WHERE num BETWEEN 5 AND 10;
|
cs |
-- 인기순위, 베스트댓글
1
2
3
|
SELECT ename,job,sal,rownum FROM emp;
SELECT ename,job,sal,rownum FROM emp
WHERE rownum<=5;
|
cs |
급여가 많은 사람 5명
1
2
3
|
SELECT ename,job,sal,rownum
FROM (SELECT ename,job,sal FROM emp ORDER BY sal DESC)
WHERE rownum<=5;
|
cs |
PROCEDURE, FUNCTION, PACKAGE, TRIGGER를 제작할 때 사용하는 언어
함수 : 사용자 정의로 사용 => 목적 (재사용)
- PROCEDURE : 리턴형이 없는 => 자바스크립트 function func_name()
- FUNCTION : 리턴형이 있는 함수
= 함수 독립
= 메소드 클래스 종속
- PACKAGE : 관련된 PROCEDURE, FUNCTION 모아서 둔 곳
- TRIGGER : 이미 지정된 이벤트 발생시에 자동 처리
=====
INSERT, UPDATE, DELETE
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
|
-- 스칼라 변수
SET serveroutput on;
DECLARE
vempno NUMBER(4);
vename VARCHAR2(20);
vjob VARCHAR2(20);
vhiredate DATE;
vsal NUMBER(7,2);
BEGIN
SELECT empno,ename,job,hiredate,sal INTO vempno,vename,vjob,vhiredate,vsal
FROM emp
WHERE empno=7788;
DBMS_OUTPUT.PUT_LINE('===== 결과 =====');
DBMS_OUTPUT.PUT_LINE('사번:'||vempno);
DBMS_OUTPUT.PUT_LINE('이름:'||vename);
DBMS_OUTPUT.PUT_LINE('직위:'||vjob);
DBMS_OUTPUT.PUT_LINE('입사일:'||vhiredate);
DBMS_OUTPUT.PUT_LINE('급여:'||vsal);
END;
-- %TYPE
DECLARE
vempno emp.empno%TYPE;
vename emp.ename%TYPE;
vjob emp.job%TYPE;
vhiredate emp.hiredate%TYPE;
vsal emp.sal%TYPE;
BEGIN
SELECT empno,ename,job,hiredate,sal INTO vempno,vename,vjob,vhiredate,vsal
FROM emp
WHERE empno=7788;
-- 출력
DBMS_OUTPUT.PUT_LINE('===== 결과 =====');
DBMS_OUTPUT.PUT_LINE('사번:'||vempno);
DBMS_OUTPUT.PUT_LINE('이름:'||vename);
DBMS_OUTPUT.PUT_LINE('직위:'||vjob);
DBMS_OUTPUT.PUT_LINE('입사일:'||vhiredate);
DBMS_OUTPUT.PUT_LINE('급여:'||vsal);
END;
-- %ROWTYPE
DESC emp;
/*
이름 널? 유형
-------- -------- ------------
EMPNO NOT NULL NUMBER(4)
ENAME VARCHAR2(10)
JOB VARCHAR2(9)
MGR NUMBER(4)
HIREDATE DATE
SAL NUMBER(7,2)
COMM NUMBER(7,2)
DEPTNO NUMBER(2)
*/
DECLARE
vemp emp%ROWTYPE;
BEGIN
SELECT * INTO vemp
FROM emp
WHERE empno=7788;
-- 출력
DBMS_OUTPUT.PUT_LINE('===== 결과 =====');
DBMS_OUTPUT.PUT_LINE('사번:'||vempno);
DBMS_OUTPUT.PUT_LINE('이름:'||vename);
DBMS_OUTPUT.PUT_LINE('직위:'||vjob);
DBMS_OUTPUT.PUT_LINE('입사일:'||vhiredate);
DBMS_OUTPUT.PUT_LINE('급여:'||vsal);
END;
-- RECORD : 사용자 정의
DECLARE
TYPE empdept IS RECORD(
empno emp.empno%TYPE,
ename emp.ename%TYPE,
dname dept.dname%TYPE,
loc dept.loc%TYPE
);
ed empdept;
BEGIN
SELECT empno,ename,dname,loc INTO ed
FROM emp, dept
WHERE emp.deptno=dept.deptno
AND empno=7788;
DBMS_OUTPUT.PUT_LINE('===== 결과 =====');
DBMS_OUTPUT.PUT_LINE('사번:'||ed.empno);
DBMS_OUTPUT.PUT_LINE('이름:'||ed.ename);
DBMS_OUTPUT.PUT_LINE('부서명:'||ed.dname);
DBMS_OUTPUT.PUT_LINE('근무지:'||ed.loc);
END;
|
cs |
-- 제어문
1. 조건문
= 단일 조건문
if(조건문) THEN => 비교연산자(=, !=, <, >, <=, >=), 논리연산자(NOT, OR, AND)
처리
END IF;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
DECLARE
-- 선언부(변수선언)
vename emp.ename%TYPE;
vjob emp.job%TYPE;
vdname dept.dname%TYPE;
vdeptno emp.deptno%TYPE;
BEGIN
-- 구현부
-- 변수에 값 대입 => :=
SELECT deptno,ename,job INTO vdeptno,vename,vjob
FROM emp
WHERE ename='KING';
IF(vdeptno=10) THEN
vdname:='개발부';
END IF;
IF(vdeptno=20) THEN
vdname:='영업부';
END IF;
IF(vdeptno=30) THEN
vdname:='총무부';
END IF;
-- 결과값 출력
DBMS_OUTPUT.PUT_LINE('===== 결과값 =====');
DBMS_OUTPUT.PUT_LINE('이름:'||vename);
DBMS_OUTPUT.PUT_LINE('부서:'||vdname);
-- 예외처리
END;
|
cs |
= 선택 조건문
IF(조건문) THEN
처리 (조건문이 TRUE)
ELSE
처리
END IF;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
DECLARE
-- 선언부(변수선언)
vename emp.ename%TYPE;
vjob emp.job%TYPE;
vdname dept.dname%TYPE;
vdeptno emp.deptno%TYPE;
BEGIN
-- 구현부
-- 변수에 값 대입 => :=
SELECT deptno,ename,job INTO vdeptno,vename,vjob
FROM emp
WHERE ename='KING';
IF(vdeptno=10) THEN
vdname:='개발부';
ELSIF(vdeptno=20) THEN
vdname:='영업부';
ELSIF(vdeptno=30) THEN
vdname:='총무부';
END IF;
-- 결과값 출력
DBMS_OUTPUT.PUT_LINE('===== 결과값 =====');
DBMS_OUTPUT.PUT_LINE('이름:'||vename);
DBMS_OUTPUT.PUT_LINE('부서:'||vdname);
-- 예외처리
END;
|
cs |
= 다중 조건문
IF(조건문) THEN
처리
ELSIF(조건문) THEN
처리
ELSIF(조건문) THEN
처리
ELSE
처리
END IF;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
DECLARE
vename emp.ename%TYPE;
vcomm emp.comm%TYPE;
vsal emp.sal%TYPE;
BEGIN
SELECT ename, comm, sal INTO vename, vcomm, vsal
FROM emp
WHERE ename='MARTIN';
-- 연산처리 => NULL값일 경우에는 결과값이 NULL이다.
IF(vcomm>0) THEN
DBMS_OUTPUT.PUT_LINE(vename||'님의 성과급은 '||vcomm||' 입니다');
ELSE
DBMS_OUTPUT.PUT_LINE(vename||'님의 성과급은 없습니다');
END IF;
END;
|
cs |
==> 선택문
CASE = TRIGGER
CASE(조건)
WHEN 조건 THEN 결과
WHEN 조건 THEN 결과
WHEN 조건 THEN 결과
ELSE
처리
END;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
-- CASE = TRIGGER
DECLARE
vempno emp.empno%TYPE;
vename emp.ename%TYPE;
vdeptno emp.deptno%TYPE;
vdname dept.dname%TYPE;
BEGIN
SELECT empno,ename,deptno INTO vempno,vename,vdeptno
FROM emp
WHERE ename='SMITH';
vdname:=CASE vdeptno
WHEN 10 THEN '개발부'
WHEN 20 THEN '총무부'
WHEN 30 THEN '자재부'
WHEN 40 THEN '신입'
END;
DBMS_OUTPUT.PUT_LINE('===== 결과 =====');
DBMS_OUTPUT.PUT_LINE('이름:'||vename);
DBMS_OUTPUT.PUT_LINE('사번:'||vempno);
DBMS_OUTPUT.PUT_LINE('부서:'||vdname);
END;
|
cs |
2. 반복문
= while
WHILE 조건 LOOP
처리
END LOOP;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
-- 반복문
WHILE 조건 LOOP
처리문장
처리문장
END LOOP;
DECLARE
i NUMBER:=1; -- 초기값
BEGIN
WHILE i<=10 LOOP
IF(MOD(i,2)=0) THEN
DBMS_OUTPUT.PUT_LINE(i);
END IF;
-- 증가식 ** =주면 안되고 := 줘야함!
i:=i+1;
-- i++ (X)
END LOOP;
END;
|
cs |
** 변수를 쓰려면 DECLARE를 사용
** IN순차 <=> IN REVERSE 역순
= for IN은증가 REVERSE는감소
FOR counter IN 1..9
FOR i IN(REVERSE) 1..9 LOOP
처리
END LOOP;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
-- FOR
/*
=============================================
형식)
FOR 변수명 IN lo..hi LOOP // 1..10
출력
END LOOP;
============================================= 코틀린
*/
BEGIN
FOR i IN 1..10 LOOP
DBMS_OUTPUT.PUT_LINE(i);
END LOOP;
END;
BEGIN
FOR i IN REVERSE 1..10 LOOP
DBMS_OUTPUT.PUT_LINE(i);
END LOOP;
END;
/
|
cs |
= basic (loop)
LOOP
문장
문장
END LOOP;
1
2
3
4
5
6
7
8
9
10
11
12
|
DECLARE
i NUMBER:=1;
BEGIN
LOOP
IF(MOD(i,2)=0) THEN
DBMS_OUTPUT.PUT_LINE(i);
END IF;
i:=i+1;
-- 종료
EXIT WHEN i>=10;
END LOOP;
END;
|
cs |
예) 정수를 입력받아서 해당 구구단을 출력하는 프로그램을 작성하시오
1
2
3
4
5
6
7
8
|
ACCEPT pno PROMPT '몇단?'
DECLARE
vno NUMBER:=&pno;
BEGIN
FOR i IN 1..9 LOOP
DBMS_OUTPUT.PUT_LINE(vno||'*'||i||'='||vno*i);
END LOOP;
END;
|
cs |
금일 수업 요약
1. 변수 선언
스칼라 변수
%TYPE
2. 연산자
비교연산자 ( = , != , < , > , <= , >= )
논리연산자 ( OR, AND, NOT )
3. 제어문
IF , IF ~ ELSE
FOR
4. SELECT에서 실행된 결과값 받는 경우 INTO
5. 변수에 값 설정 ===> :=
=> 단일행 서브 쿼리
스칼라 서브 쿼리
인라인 뷰
커서 : 여러개 데이터를 저장하는 공간
CURSOR emp_cur IS
SELECT * FROM emp;
'Back-end > Oracle' 카테고리의 다른 글
Oracle 21일차 - Trigger (0) | 2020.11.16 |
---|---|
Oracle 20일차 - Cursor, Function (0) | 2020.11.11 |
Oracle 17일차 - 답변형 게시판 (0) | 2020.08.27 |
Oracle 16일차 - 지니뮤직, 멜론뮤직 출력 (0) | 2020.08.26 |
Oracle 15일차 - 인라인뷰 (0) | 2020.08.25 |