오늘의 코딩순서 + 포인트
1) SUB Query
: 하나의 SQL 명령문의 결과를 다른 SQL 명령문에 전달하기 위해 두 개 이상의 SQL 명령문을 하나의 SQL명령문으로 연결하여 처리하는 방법
예시)
1-1. 교수 테이블에서 ‘전은지’ 교수와 직급이 동일한 모든 교수의 이름 검색
SELECT position
FROM professor
WHERE name = '전은지'
;
1-2. 교수 테이블의 직급 칼럼에서 1 에서 얻은 결과 값과 동일한 직급을 가진 교수 검색 명령문 실행
SELECT name , position
FROM professor
WHERE position = '전임강사'
;
1-3. 교수 테이블에서 ‘전은지’ 교수와 직급이 동일한 모든 교수의 이름 검색--> SUB Query
SELECT name , position
FROM professor
WHERE position = (
SELECT position
FROM professor
WHERE name = '전은지'
)
;
1-1. 단일행 서브쿼리
- 서브쿼리에서 단 하나의 행만을 검색하여 메인쿼리에 반환하는 질의문
- 메인쿼리의 WHERE 절에서 서브쿼리의 결과와 비교할 경우에는 반드시 단일행 비교 연산자 중 하나만 사용해야함
문제 1-1) 사용자 아이디가 ‘jun123’인 학생과 같은 학년인 학생의 학번, 이름, 학년을 출력하여라
SELECT studno , name , grade
FROM student
WHERE grade = (
SELECT userid
FROM student
WHERE userid = 'jun123'
)
;
문제 1-2) 101번 학과 학생들의 평균 몸무게보다 몸무게가 적은 학생의 이름, 학년 , 학과번호, 몸무게를 출력
-- 조건 : 학과별 올림차순 출력
SELECT name , grade , deptno , weight
FROM student
WHERE weight < (
SELECT AVG(weight)
FROM student
WHERE deptno = 101
)
ORDER BY deptno
;
문제 1-3) 20101번 학생과 학년이 같고, 키는 20101번 학생보다 큰 학생의 이름, 학년, 키, 학과명을 출력하여라
-- 조건 : 학과별 내림차순 출력 ===> 가장 기본적인 문제, Join을 섞어 사용하기
SELECT s.name , s.grade , s.height , d.dname
FROM student s , department d
WHERE s.deptno = d.deptno
AND s.grade = (
--1.같은 학년
SELECT grade
FROM student
WHERE studno = 20101
)
AND s.height > (
--2. 20101번 학생보다 큰 키
SELECT height
FROM student
WHERE studno = 20101
)
ORDER BY d.dname DESC
;
1-2. 다중행 서브쿼리
- 서브쿼리에서 반환되는 결과 행이 하나 이상일 때 사용하는 서브쿼리
- 메인쿼리의 WHERE 절에서 서브쿼리의 결과와 비교할 경우에는 다중 행 비교 연산자 를 사용하여 비교
- 다중 행 비교 연산자 : IN, ANY, SOME, ALL, EXISTS
- IN: 메인 쿼리의 비교 조건이 서브쿼리의 결과중에서 하나라도 일치하면 참, ‘=‘비교만 가능
- ANY, SOME: 메인 쿼리의 비교 조건이 서브쿼리의 결과중에서 하나라도 일치하면 참
- ALL: 메인 쿼리의 비교 조건이 서브쿼리의 결과중에서 모든값이 일치하면 참
- EXISTS : 메인 쿼리의 비교 조건이 서브쿼리의 결과중에서 만족하는 값이 하나라도 존재하면 참
-- 1. IN 연산자를 이용한 다중행 서브쿼리
----이렇게 하면 오류남
SELECT name , grade , deptno
FROM student
WHERE deptno = ( -- '='은 하나의 값을 뜻함
SELECT deptno
FROM department
WHERE college = 100
)
;
오류: single-row subquery returns more than one row
오류나는 이유: 단일행 하위 질의에 2개 이상의 행이 리턴되었기 때문
↓↓↓ 따라서 다중행 서브쿼리를 사용해야 한다
SELECT name , grade , deptno
FROM student
WHERE deptno IN (
SELECT deptno
FROM department
WHERE college = 100
)
;
SELECT name , grade , deptno
FROM student
WHERE deptno IN (
101,102
)
;
-- 2. ANY 연산자를 이용한 다중행 서브쿼리
문제 1-4)모든 학생 중에서 4학년 학생 중에서 키가 제일 작은 학생보다 키가 큰 학생의 학번, 이름, 키를 출력하여라
SELECT studno , name , height
FROM student
WHERE height > ANY ( -- ANY: 어떤 것이라도 ==>'키가 제일 작은 학생보다'라는 조건에 부합함 ==> min을 생각하면 됨
SELECT height
FROM student
WHERE grade = '4'
)
;
--- 3. ALL 연산자를 이용한 다중행 서브쿼리 (위 문제 사용)
SELECT studno , name , height
FROM student
WHERE height > ALL ( -- ALL: max를 생각하면 됨
SELECT height
FROM student
WHERE grade = '4'
)
;
--- 4. ⭐EXISTS 연산자를 이용한 다중행 서브쿼리 : if문 같은것 (현장에서 많이 쓰임)
SELECT profno , name , sal , comm , position
FROM professor
WHERE EXISTS ( --EXISTS: 아래 조건에 해당하는 것이 1 Row라도 존재하면 위를 실행시켜라
SELECT position
FROM professor
WHERE comm IS NOT NULL
)
;
SELECT profno , name , sal , comm , position
FROM professor
WHERE EXISTS (
SELECT position
FROM professor
-- WHERE deptno = 202 -- 202였다면 존재하니까 출력됨
WHERE deptno = 203 ---but, 203의 row값은 존재하지 않기 때문에 아예 출력값이 X
)
;
문제 1-5) 보직수당을 받는 교수가 한 명이라도 있으면 모든 교수의 교수 번호, 이름, 보직수당 그리고 급여와 보직수당의 합(NULL처리)을 출력
SELECT profno , name , sal , comm , sal + NVL(comm,0) sal_comm
FROM professor
WHERE EXISTS (
SELECT profno
FROM professor
WHERE comm IS NOT NULL
)
;
1-3. 다중컬럼 서브쿼리
- 서브쿼리에서 여러 개의 칼럼 값을 검색하여 메인쿼리의 조건절과 비교하는 서브쿼리
- 메인쿼리의 조건절에서도 서브쿼리의 칼럼 수만큼 지정
- 종류
- 1) PAIRWISE : 칼럼을 쌍으로 묶어서(괄호로 묶어서) 동시에 비교하는 방식
- 2) UNPAIRWISE : 칼럼별로 나누어서 비교한 후, AND 연산을 하는 방식
- 둘의 결과는 완전히 다름
-- 1. PAIRWISE : 칼럼을 쌍으로 묶어서(괄호로 묶어서) 동시에 비교하는 방식
문제1-6) PAIRWISE 비교 방법에 의해 학년별로 몸무게가 최소인 학생의 이름, 학년, 몸무게를 출력하여라
SELECT name , grade , weight
FROM student
WHERE (grade,weight) IN (SELECT grade, MIN(weight)
FROM student
GROUP BY grade
)
;
-- 2) UNPAIRWISE : 칼럼별로 나누어서 비교한 후, AND 연산을 하는 방식
문제1-7) UNPAIRWISE 비교 방법에 의해 학년별로 몸무게가 최소인 학생의 이름, 학년, 몸무게를 출력
SELECT name , grade , weight
FROM student
-- 1,2,3,4
WHERE grade IN (SELECT grade
FROM student
GROUP BY grade)
--52,42,70,72
AND weight IN (SELECT MIN(weight)
FROM student
GROUP BY grade)
;
-- 3) 상호연관 서브쿼리 ⭐⭐⭐(난이도↑↑) : 메인쿼리절과 서브쿼리간에 검색 결과를 교환하는 서브쿼리
문제1-8 ) 각 학과 학생의 평균 키보다 키가 큰 학생의 이름, 학과 번호, 키를 출력하여라
SELECT deptno , name , grade , height --실행순서1
-- 2번순서 실행 후 한번 더 마지막으로실행
FROM student s1
WHERE height > (SELECT AVG(height)
FROM student s2
-- WHERE s2.deptno = 101
-- 실행순서 2
WHERE s2.deptno = s1.deptno
)
ORDER BY deptno
;
2) 테이블관리
1. 다중 행 입력
1. 생성된 TBL이용 신규 TBL 생성
CREATE Table dept_second
AS SELECT * FROM dept
;
2. TBL 가공 생성
CREATE Table emp20
AS SELECT empno , ename , sal*12 annsal
FROM emp
WHERE deptno = 20
;
3.TBL 구조만
CREATE Table dept30
AS SELECT deptno , dname
FROM dept
WHERE 0=1
-- 0=1: 윗줄까지만 쓰면 deptno,dname의 데이터값까지 가져오지만,
-- WHERE 0=1을 쓰면 구조만 가져오고 데이터값은 가져오지 않는다
;
4. Column 추가
ALTER TABLE dept30
ADD(birth Date)
;
INSERT INTO dept30 VALUES (10,'중앙학교',sysdate)
;
5. Column 변경
ALTER TABLE dept30
Modify dname varchar2(11) --cannot decrease column length because some value is too big
; --'중앙학교'는 12byte, 11보다 커서 크기 변경 불가
ALTER TABLE dept30
Modify dname varchar2(30)
;
6. Column 삭제
ALTER TABLE dept30
Drop Column dname
;
7. TBL명 변경
RENAME dept30 TO dept35;
8. TBL 제거
DROP Table dept35;
9. Truncate
TRUNCATE table dept_second;
+ DELETE, DROP, TRUNCATE 비교⭐⭐⭐⭐⭐
(DML,DDL은 https://mycodingdiary1219.tistory.com/28 참고)
비교항목 | DELETE | TRUNCATE | DROP |
⭐명령어 분류 | DML | DDL | DDL |
삭제범위 | ⭐행 데이터 일부 ~ 전체 | ⭐행 전체 + 인덱스 등 | ⭐행 전체+ 인덱스 + 테이블 전체 |
행 데이터(레코드) | 일부 ~ 전체삭제 | 전체 삭제 | 전체 삭제 |
데이터 저장공간 | 남겨져있음 | 삭제됨 | 삭제됨 |
인덱스 | 남겨져있음 | 삭제됨 | 삭제됨 |
테이블 컬럼, 제약조건 | 남겨져있음 | 남겨져있음 | 삭제됨 |
테이블 정의 | 남겨져있음 | 남겨져있음 | 삭제됨 |
작업속도 | 느림 | 빠름 | 빠름 |
복구가능성 | 있음 | 일부 가능 | 없음 |
- '삭제'라는 공통점을 갖지만, 삭제의 범주와 대상이 다름
- 범주의 크기는 DELETE < TRUNCATE < DROP 순
- DELETE: 행 일부 또는 전체 데이터를 지움, 정의된 테이블자체는 남아있음
- TRUNCATE: 행 전체 데이터 + 행이 저장되어있던 공간과 인덱스까지 지움, 정의된 테이블자체는 남아있음
- DROP: 행 데이터 + 인덱스 뿐 아니라 테이블 전체까지 완전히 제거
테이블 정의는 DROP 명령어를 사용한 테이블 삭제일 경우만 가능하며, 나머지 경우는 테이블의 정의가 남는다
- DELETE를 제외하고 TRUNCATE와 DROP는 사용공간(저장공간)을 반납하여 다른 곳에서 해당공간을 재사용할 수 있다
- DELETE를 이용한 데이터 삭제의 경우 삭제되는 행마다 로그를 기록하기 떄문에 작업 속도가 저하된다
3) 데이터 조작어 (DML:Data Manpulation Language)
- 정의 : 테이블에 새로운 데이터를 입력하거나 기존 데이터를 수정 또는 삭제하기 위한 명령어
- 종류
- 1) INSERT : 새로운 데이터 입력 명령어
- 2) UPDATE : 기존 데이터 수정 명령어
- 3) DELETE : 기존 데이터 삭제 명령어
- 4) MERGE : 두개의 테이블을 하나의 테이블로 병합하는 명령어
1. INSERT
예시)
INSERT INTO DEPT VALUES (73,'인사');
INSERT INTO DEPT VALUES (73,'인사','이대'); --이걸 써야 삽입됨
INSERT INTO DEPT (deptno , Dname , LOC) VALUES(74,'회계팀','충정로'); --위치를 맞췄기 때문에 삽입가능
INSERT INTO DEPT (deptno , LOC , Dname) VALUES(75,'신대방','자제팀'); --위치를 맞추지 않아서 삽입 불가능
INSERT INTO DEPT (deptno , LOC) VALUES (76,'홍대');
문제2-1) professor TBL에 새로 삽입하기
INSERT INTO professor (profno , name , position , hiredate , deptno)
VALUES (9920 , '최윤식' , '조교수' , TO_DATE('2006/01/01','YYYY/MM/DD'), 102);
INSERT INTO professor (profno , name , position , hiredate , deptno)
VALUES (9910 , '백미선' , '전임강사' , sysdate , 101);
>>>JOB3테이블 새로 생성 후 밑에 문제 시작
문제2-2)
INSERT INTO JOB3 VALUES (10,'학교');
INSERT INTO JOB3(jobno , jobname) VALUES (11,'공무원');
INSERT INTO JOB3(jobname , jobno) VALUES ('공기업',12);
INSERT INTO JOB3 VALUES (13,'대기업');
INSERT INTO JOB3 VALUES (14,'중소기업');
1-1. INSERT ALL(unconditional INSERT ALL) 명령문
height_info, weight_info TBL 먼저 생성
CREATE TABLE height_info
( studNo number(5),
NAME VARCHAR2(20),
height number(5,2)
);
CREATE TABLE weight_info
( studNo number(5),
NAME VARCHAR2(20),
weight number(5,2)
);
INSERT ALL
INTO height_info VALUES(studNo , name , height)
INTO weight_info VALUES(studNo , name , weight)
SELECT studno , name , height , weight , grade
FROM student
WHERE grade >= '2' --조건: grade가 2보다 클 것
;
↓↓↓ 아래 조건절로 하면 각 테이블마다 조건을 세분화해서 입력가능
INSERT ALL
[WHEN 조건절1 THEN
INTO [table1] VLAUES[(column1, column2,…)]
[WHEN 조건절2 THEN
INTO [table2] VLAUES[(column1, column2,…)]
[ELSE
INTO [table3] VLAUES[(column1, column2,…)]
subquery;
문제 2-3) 학생 테이블에서 2학년 이상의 학생을 검색하여
height_info 테이블에는 키가 170보다 큰 학생의 학번, 이름, 키를 입력, weight_info 테이블에는 몸무게가 75보다 큰 학생의 학번, 이름, 몸무게를 각각 입력하여라
INSERT ALL
WHEN height > 170 Then
INTO height_info VALUES(studNo , name , height)
WHEN weight > 75 Then
INTO weight_info VALUES(studNo , name , weight)
SELECT studno , name, height , weight
FROM student
WHERE grade >= '2'
;
2. Update
- 데이터 수정 개요
- UPDATE 명령문은 테이블에 저장된 데이터 수정을 위한 조작어
- WHERE 절을 생략하면 테이블의 모든 행을 수정
문제 2-4) 교수 번호가 9903인 교수의 현재 직급을 ‘부교수’로 수정하여라
UPDATE professor
SET position = '부교수',userid = 'kkk'
WHERE profno = 9903
;
문제 2-5) 서브쿼리를 이용하여 학번이 10201인 학생의 학년과 학과 번호를 10103 학번 학생의 학년과 학과 번호와 동일하게 수정하여라
UPDATE student
SET (grade , deptno) = (
SELECT grade , deptno
FROM student
WHERE studno = 10103
)
WHERE studno = 10201
;
3. DELETE
- 데이터 삭제 개요
- DELETE 명령문은 테이블에 저장된 데이터 삭제를 위한 조작어
- WHERE 절을 생략하면 테이블의 모든 행 삭제
문제 2-6) 학생 테이블에서 학번이 20103인 학생의 데이터를 삭제
DELETE
FROM student
WHERE studno = 20103
;
문제 2-7) 학생 테이블에서 컴퓨터공학과에 소속된 학생을 모두 삭제하여라.
DELETE
FROM student
WHERE deptno = ( SELECT deptno
FROM department
WHERE dname = '컴퓨터공학과'
)
;
4. MERGE
- 구조가 같은 두개의 테이블을 비교하여 하나의 테이블로 합치기 위한 데이터 조작어
- WHEN 절의 조건절에서 결과 테이블에 해당 행이 존재하면 UPDATE 명령문에 의해 새로운 값으로 수정,
- 그렇지 않으면 INSERT 명령문으로 새로운 행을 삽입
예비작업 1)
CREATE TABLE professor_temp
AS SELECT * FROM professor
WHERE position = '교수'
;
UPDATE professor_temp
SET position = '명예교수'
WHERE position = ' 교수'
;
INSERT INTO professor_temp
VALUES (9999,'김도경','arom21','전임강사',200,sysdate , 10, 101)
;
commit;
예비작업 2) professor MERGE 수행
목표 : professor_temp에 있는 직위 수정된 내용을 professor Table에 Update
김도경 씨가 신규 Insert 내용을 professor Table에 Insert
-- 1) 교수가 명예교수로 2행 Update
-- 2) 김도경 씨가 신규 Insert
MERGE INTO professor p
USING professor_temp f
ON (p.profno = f.profno)
when matched then --PK(Primary Key)가 같으면 직위를 Update
update set p.position = f.position
when not matched then --PK가 없으면 신규 Insert
insert values(f.profno , f.name , f.userid , f.position , f.sal , f.hiredate , f.comm , f.deptno)
;
오늘의 숙제
Inner Join 이용
1. 이름, 관리자명(emp TBL)
>>내가 한 것
SELECT e.ename , m.mgr
FROM emp e , emp m
WHERE e.empno = m.empno
;
>>선생님이 한 것
SELECT w.ename , m.ename 관리자
FROM emp w , emp m
WHERE w.mgr = m.empno
;
2. 이름,급여,부서코드,부서명,근무지, 관리자 명, 전체직원(emp ,dept TBL) --Join 3개
>>내가 한 것
SELECT e.ename , e.sal , e.empno , d.dname , d.loc, e.mgr
FROM emp e , dept d
WHERE e.deptno = d.deptno
;
>>선생님이 한 것
SELECT w.ename , w.sal , w.deptn o , dname , loc , m.ename 관리자
FROM emp w , emp m , dept d
WHERE w.deptno = d.deptno
AND w.mgr = m.empno(+)
;
3. 이름,급여,등급,부서명,관리자명, 급여가 2000이상인 사람 (emp, dept,salgrade TBL)
>>내가 한 것
SELECT e.ename , e.sal , s.grade , d.dname , e.mgr
FROM emp e , dept d, salgrade s
WHERE e.deptno = d.deptno
AND sal >= 2000
;
>>선생님이 한 것
SELECT w.ename , w.sal , s.grade , dname , m.ename
FROM emp w , emp m , dept d , salgrade s
WHERE w.mgr = m.empno
AND w.deptno = d.deptno
AND w.sal BETWEEN s.losal AND s.hisal
AND w.sal>=2000
;
>>성능을 높이려면?
SELECT w.ename , w.sal , grade , dname , m.ename
FROM ( SELECT * FROM emp WHERE w.sal >= 2000) w
, emp m
, dept d
, salgrade s
WHERE w.mgr = m.empno
AND w.deptno = d.deptno
AND w.sal BETWEEN s.losal AND s.hisal
;
4. 보너스를 받는 사원에 대하여 이름,부서명,위치를 출력하는 SELECT 문장을 작성emp ,dept TBL)
>>내가 한 것
SELECT e.ename , d.dname , d.loc
FROM emp e , dept d
WHERE e.deptno = d.deptno
AND comm>0
;
>>선생님이 한 것
SELECT e.ename , d.dname , d.loc
FROM emp e , dept d
WHERE e.deptno = d.deptno
AND e.comm>0
;
5. 사번, 사원명, 부서코드, 부서명을 검색하라. 사원명기준으로 오름차순정열(emp ,dept TBL)
>>내가 한 것
SELECT e.empno , e.ename , d.deptno , d.dname
FROM emp e , dept d
WHERE e.deptno = d.deptno
ORDER BY e.ename
;
>>선생님이 한 것 = 나와 같음
SUB Query 이용 (EMP TABLE)
-- 1. Blake와 같은 부서에 있는 모든 사원에 대해서 사원 이름과 입사일을 디스플레이하라
>>내가 한 것
SELECT ename , hiredate
FROM emp
WHERE deptno = (
SELECT deptno
FROM emp
WHERE ename = 'BLAKE'
)
;
>>선생님이 한 것
SELECT ename , hiredate , deptno
FROM emp
WHERE deptno = (
SELECT deptno
FROM emp
WHERE INITCAP(ename) = 'BLAKE'
)
;
-- 2. 평균 급여 이상을 받는 모든 사원에 대해서 사원 번호와 이름을 디스플레이하는 질의문을 생성.
-- 단 출력은 급여 내림차순 정렬하라
>>내가 한 것
SELECT ename , empno , sal
FROM emp
WHERE sal > (
SELECT AVG(sal)
FROM emp
)
ORDER BY sal DESC
;
>>선생님이 한 것 = 나와 같음
-- 3. 보너스를 받는 어떤 사원의 부서 번호와
-- 급여에 일치하는 사원의 이름, 부서 번호 그리고 급여를 디스플레이하라.
>>내가 한 것
SELECT ename , deptno , sal
FROM emp
WHERE sal IN (
SELECT d.deptno , e.ename
FROM emp d , emp e
WHERE d.sal = e.sal
AND comm > 0
)
;
>>선생님이 한 것
SELECT ename , deptno , sal
FROM emp
WHERE (deptno , sal) IN
SELECT deptno , sal
FROM emp
WHERE comm IS NOT NULL
)
;
데이터 조작어 이용
CREATE TABLE Religion
( religion_no NUMBER(2) CONSTRAINT PK_ReligionNo3 PRIMARY KEY,
religion_name VARCHAR2(20)
) ;
--10 기독교
--20 카톨릭교
--30 불교
--40 무교
>>내가 한 것
INSERT INTO RELIGION VALUES (10,'기독교');
INSERT INTO RELIGION VALUES (20,'카톨릭교');
INSERT INTO RELIGION VALUES (30,'불교');
INSERT INTO RELIGION VALUES (40,'무교');
>>선생님이 한 것
INSERT INTO RELIGION (religion_no , religion_name) VALUES (10,'기독교');
INSERT INTO RELIGION (religion_name , religion_no) VALUES ('카톨릭교',20);
INSERT INTO RELIGION VALUES (30,'불교');
INSERT INTO RELIGION VALUES (40,'무교');
'DB > Oracle' 카테고리의 다른 글
2024_07_02_화 (0) | 2024.07.02 |
---|---|
2024_07_01_월 (0) | 2024.07.01 |
2024_06_27_목 (0) | 2024.06.27 |
2024_06_26_수 (0) | 2024.06.26 |
2024_06_26_수 (0) | 2024.06.26 |