일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- Python
- 에러
- error
- PHPStorm
- github clone
- 클론
- visualstudio code
- Visual Studio Code
- OrCAD 다운로드
- localhost
- 따옴표 삭제
- 오류
- vscode
- cmd
- console창
- clone
- run sql script
- 깃 토큰
- 단축키
- 파이썬
- 데이터베이스
- database
- import data
- csv
- error 해결
- github token
- php
- DataGrip
- jupyter
- MySQL
Archives
- Today
- Total
개발 노트
8/10 서브쿼리, DML(INSERT, UPDATE, DELETE, MERGE), DELETE와 DROP과 TRUNCATE 비교 본문
프로젝트 기반 JAVA 응용 SW개발 : 22.07.19~23.01.20/Oracle SQL
8/10 서브쿼리, DML(INSERT, UPDATE, DELETE, MERGE), DELETE와 DROP과 TRUNCATE 비교
hayoung.dev 2022. 8. 10. 20:43[서브쿼리의 개념]
서브쿼리가 먼저 실행되고 메인쿼리가 실행된다.
--SUB Query(중요, 별 3개)--
--하나의 SQL 명령문의 결과를 다른 SQL 명령문에 전달하기 위해
--두 개 이상의 SQL 명령문을 하나의 SQL명령문으로 연결하여 처리하는 방법
--1-1. 목표 : 교수 테이블에서 ‘전은지’ 교수와 직급이 동일한 모든 교수의 이름 검색(서브쿼리 이용하지 않음)
--1) 교수 테이블에서 ‘전은지’ 교수의 직급 검색 SQL 명령문 실행
SELECT position FROM professor WHERE name='전은지';
--2) 교수 테이블의 직급 칼럼에서 1 에서 얻은 결과 값과 동일한 직급을 가진 교수 검색 명령문 실행
SELECT name, position FROM professor WHERE position='전임강사';
--1-2. 목표 : 교수 테이블에서 ‘전은지’ 교수와 직급이 동일한 모든 교수의 이름 검색(서브쿼리 이용)
SELECT name, position FROM professor
WHERE position = (SELECT position FROM professor WHERE name = '전은지');
--종류
--1. 단일행 서브쿼리
--서브쿼리에서 단 하나의 행만을 검색하여 메인쿼리에 반환하는 질의문
--메인쿼리의 WHERE 절에서 서브쿼리의 결과와 비교할 경우에는 반드시 단일행 비교 연산자 중 하나만 사용해야함
--단일행은 서브쿼리(괄호 안)의 결과값이 하나만 나오는 것이 단일행이다.
--문1) 사용자 아이디가 ‘jun123’인 학생과 같은 학년인 학생의 학번, 이름, 학년을 출력하여라
SELECT studno, name, grade FROM student
WHERE grade = (SELECT grade FROM student WHERE userid = 'jun123');
--문2)101번 학과 학생들의 평균 몸무게보다 몸무게가 적은 학생의 이름, 학과번호, 몸무게를 출력(학과 별 오름차순 출력)
SELECT name, deptno, weight
FROM student
WHERE weight < (SELECT AVG(WEIGHT) FROM student WHERE deptno = 101)
ORDER BY deptno;
--문3) 20101번 학생과 학년이 같고, 키는 20101번 학생보다 큰 학생의 이름, 학년, 키를 출력하여라
SELECT name, grade, height
FROM student
WHERE grade = (
SELECT grade
FROM student
WHERE studno = '20101')
and height > (
SELECT height
FROM student
WHERE studno ='20101');
--문4) 101번 학과 학생들의 평균 몸무게보다 몸무게가 적은 학생의 이름, 학과번호, 몸무게를 출력하여라. (학과별 출력)
SELECT name, deptno, weight FROM student
WHERE weight <
( SELECT AVG(weight) FROM student WHERE deptno = '101')
ORDER BY deptno;
--2. 다중행 서브쿼리
--서브쿼리에서 반환되는 결과 행이 하나 이상일 때 사용하는 서브쿼리
--메인쿼리의 WHERE 절에서 서브쿼리의 결과와 비교할 경우에는 다중 행 비교 연산자를 사용하여 비교
--다중 행 비교 연산자 : IN, ANY, SOME, ALL, EXISTS
--1) IN : 메인 쿼리의 비교 조건이 서브쿼리의 결과중에서 하나라도 일치하면(즉 or이면) 참, ‘=‘비교만 가능
--2) ANY, SOME : 메인 쿼리의 비교 조건이 서브쿼리의 결과중에서 하나라도 일치하면(즉 or이면) 참
--3) ALL : 메인 쿼리의 비교 조건이 서브쿼리의 결과중에서 모든값이 일치하면(즉 and이면) 참
--4) EXISTS : 메인 쿼리의 비교 조건이 서브쿼리의 결과중에서 만족하는 값이 하나라도 존재하면 참. (중요 : 많이 쓰이므로 알아두기)
--1) IN 연산자를 이용한 다중 행 서브쿼리
-- 괄호 안에 있는 값이 하나 이상이면 다중행 서브쿼리를 통해 받아야 한다.
-- 오류 발생 : "single-row subquery returns more than one row"
SELECT name, grade, deptno
FROM student
WHERE deptno = (
SELECT deptno
FROM department
WHERE college = 100);
-- 오류 해결 : 다중행 쿼리를 사용
SELECT name, grade, deptno
FROM student
WHERE deptno IN (
-- 101, 102
SELECT deptno
FROM department
WHERE college = 100);
--2) ANY 연산자를 이용한 다중 행 서브쿼리
--문1) 모든 학생 중에서 4학년 학생 중에서 키가 제일 작은 학생보다 키가 큰 학생의 학번, 이름, 키를 출력하여라
SELECT studno, name, height
FROM student
WHERE height > ANY (
-- 175,176,177
-- 이 값 중 어떤것 보다도 커야 하므로(or 이므로) 175보다 크면 된다.
SELECT height
FROM student
WHERE grade = '4');
--3) ALL 연산자를 이용한 다중 행 서브쿼리
--문2) 모든 학생 중에서 4학년 학생 중에서 키가 제일 큰 학생보다 키가 큰 학생의 학번, 이름, 키를 출력하여라
SELECT studno, name, height
FROM student
WHERE height > ALL (
-- 175,176,177
-- 이 값 모두보다 커야 하므로(and 이므로) 177보다 커야 한다.
SELECT height
FROM student
WHERE grade = '4');
--4) EXISTS 연산자를 이용한 다중 행 서브쿼리
--괄호 안의 값과 인과관계가 전혀 없다. 괄호 안을 만족하는 데이터가 하나라도 존재하면 실행하는 것임.
--그래서 괄호 안의 select문은 중요하지 않고
--괄호 안에 해당하는 데이터의 존재만 중요한 것이다.
--그래서 성능 최적화에 아주 좋다.
SELECT profno, name, sal, comm, position
FROM professor
WHERE EXISTS (
SELECT position
FROM professor
WHERE comm IS NOT NULL
);
SELECT profno, name, sal,comm, position
FROM professor
WHERE EXISTS (
SELECT sal
FROM professor
WHERE position = '교수'
);
SELECT profno, name, sal, comm, position
FROM professor
WHERE EXISTS (
SELECT * FROM EMP WHERE empno = 1000
);
--문1) 보직수당을 받는 교수가 한 명이라도 있으면
--모든 교수의 교수 번호, 이름, 보직수당 그리고 급여와 보직수당의 합을 출력
SELECT profno, name, comm, NVL(comm, 0)+sal
FROM professor
WHERE EXISTS (
SELECT comm
FROM professor
WHERE COMM IS NOT NULL);
--문2) 학생 중에서 ‘goodstudent’이라는 사용자 아이디가 없으면 1을 출력하여라
SELECT 1 USERID_EX
FROM dual
WHERE NOT EXISTS (
SELECT userid
FROM student
WHERE userid = 'goodstudent');
--3. 다중 컬럼 서브쿼리
--서브쿼리에서 여러 개의 칼럼 값을 검색하여 메인쿼리의 조건절과 비교하는 서브쿼리
--메인쿼리의 조건절에서도 서브쿼리의 칼럼 수만큼 지정
--종류
--1) PAIRWISE : 괄호 안에서 칼럼을 쌍으로 묶어서 괄호 밖에서 동시에 비교하는 방식
--2) UNPAIRWISE : 괄호 안에서 칼럼별로 나누어서 비교한 후 괄호 밖에서 AND 연산을 하는 방식
--1) PAIRWISE 다중 칼럼 서브쿼리
--문1) PAIRWISE 비교 방법에 의해 학년별로 몸무게가 최소인 학생의 이름, 학년, 몸무게를 출력하여라
SELECT name, grade, weight
FROM student
WHERE (grade, weight) IN (SELECT grade, MIN(weight)
FROM student
GROUP BY grade);
--2) UNPAIRWISE
--UNPAIRWISE 비교 방법에 의해 학년별로 몸무게가 최소인 학생의 이름, 학년, 몸무게를 출력
SELECT name, grade, weight
FROM student
--group by로 들어간 게 in이라서 1 or 2 or 3 or 4가 됨.
WHERE grade IN(SELECT grade
FROM student
GROUP BY grade)
--괄호 안은 52, 70, 72, 42(전부 or)
AND weight IN (SELECT MIN(weight)
FROM student
GROUP BY grade);
--최종적으로는 and로 엮음.
--그래서 잘못 섞였기 때문에 UNPAIRWISE가 아닌 PAIRWISE를 사용하여야 한다.
--이렇게 의도하지 않은 결과가 나올 수 있기 때문에 잘 써야 한다.
--4. 상호연관 서브쿼리 ***(중요 : 별 3개)
-- 메인쿼리절과 서브쿼리간에 검색 결과를 교환하는 서브쿼리
--문1) 각 학과 학생의 평균 키보다 키가 큰 학생의 이름, 학과 번호, 키를 출력하여라
--실행 순서가 주고받기 때문에 상호연관 서브쿼리이다.
SELECT deptno, name, grade, height --실행순서(1), (3)
FROM student s1
WHERE height > (SELECT AVG(height)
FROM student s2
--WHERE s2.deptno = 101 --괄호 안 쿼리문 테스트할 때 주석문 지우고 사용.
WHERE s2.deptno = s1.deptno --(2)
)
ORDER BY deptno;
[과제]
------------- HW -----------------------
-- 1. Blake와 같은 부서에 있는 모든 사원에 대해서 사원 이름과 입사일을 디스플레이하라
SELECT e.ename, e.hiredate, deptno
FROM emp e
WHERE e.deptno = (
SELECT e.deptno
FROM emp e
WHERE INITCAP(e.ename) = 'Blake');
-- 2. 평균 급여 이상을 받는 모든 사원에 대해서 사원 번호와 이름을 디스플레이하는 질의문을 생성.
-- 단 출력은 급여 내림차순 정렬하라
SELECT empno, ename, sal
FROM emp
WHERE sal > (
SELECT AVG(sal)
FROM emp)
ORDER BY sal DESC;
-- 3. 보너스를 받는 어떤 사원의 부서 번호와
-- 급여에 일치하는 사원의 이름, 부서 번호 그리고 급여를 디스플레이하라.
SELECT ename, deptno, sal
FROM emp
WHERE comm IS NOT NULL;
--정답
SELECT ename, deptno, sal
FROM emp
WHERE (deptno, sal) IN
(SELECT deptno, sal
FROM emp
WHERE comm IS NOT NULL);
--데이터 조작어 (DML:Data Manpulation Language) (중요 : 별 2개)
--테이블에 새로운 데이터를 입력하거나 기존 데이터를 수정 또는 삭제하기 위한 명령어
--종류
--INSERT : 새로운 데이터 입력 명령어
--UPDATE : 기존 데이터 수정 명령어
--DELETE : 기존 데이터 삭제 명령어
--MERGE : 두개의 테이블을 하나의 테이블로 병합하는 명령어
--1) INSERT
--컬럼명을 지정 안하면 순서대로 들어감.
--컬럼에 데이터 전체 넣을 거면 컬럼명 지정 안해도 괜찮다. 대신 순서 지키기
--데이터 전체를 넣을 것이 아니라면 컬럼명을 지정해주는 것이 좋다.
INSERT INTO dept VALUES(71, '인사', '이대');
--컬럼 수에 맞지 않게 넣으면 오류남.
INSERT INTO dept VALUES(71, '인사');
--컬럼명을 지정하고 넣으면 데이터가 순서대로 들어감.
INSERT INTO dept (deptno, dname, loc) VALUES (72, '회계팀', '충정로');
--이렇게 컬럼명의 순서를 바꿔도 지정한 컬럼명 순서대로 데이터가 들어감.
INSERT INTO dept (deptno, loc, dname) VALUES (75, '회계팀', '충정로');
--컬럼명을 지정하고 컬럼수를 맞지 않게 넣으면 데이터를 넣지 않은 부분은 null이 됨.
INSERT INTO dept (deptno, loc) VALUES (73, '홍대');
--deptno가 primary key인데, primary key의 유일성을 위반하기 때문에 데이터가 들어가지 않음.
INSERT INTO dept (deptno, loc, dname) VALUES (75, '자재팀', '신대방');
--제약조건에서 not null로 설정한 항목에 null값을 넣으면 오류가 남.
INSERT INTO dept(deptno, loc) VALUES (77, '당산');
INSERT INTO professor (profno, name, position, hierdate, deptno) VALUES (9910, '백미선', '전임강사', '22/08/10', 101);
INSERT INTO professor (profno, name, position, hierdate, deptno) VALUES (9920, '최윤식', '조교수', '06/01/01', 102);
--하단 방법으로 해도 됨.
--INSERT INTO professor (profno, name, position, hierdate, deptno) VALUES (9910, '백미선', '전임강사', SYSDATE), 101);
--INSERT INTO professor (profno, name, position, hierdate, deptno) VALUES (9920, '최윤식', '조교수', TO_DATE('2006/01/01', 'YYYY/MM/DD', 102);
CREATE TABLE JOB3
--기본키에 별명을 지어주지 않으면 시스템이 임의로 짓기 때문에 관리하기 힘들다.
(jobno VARCHAR2(2) PRIMARY KEY,
jobname VARCHAR2(20)
);
INSERT INTO JOB3 VALUES (10,'학교');
INSERT INTO JOB3(jobno,jobname) VALUES (11,'공무원');
INSERT INTO JOB3(jobno,jobname) VALUES (12,'공기업');
INSERT INTO JOB3 VALUES (13,'대기업');
INSERT INTO JOB3 VALUES (14,'중소기업');
CREATE TABLE Religion
--이렇게 기본키에 별명을 지어주어야 제약조건의 이름을 잘 기억할 수 있기 때문에 좋다.
( religion_no NUMBER(2) CONSTRAINT PK_ReligionNo3 PRIMARY KEY,
religion_name VARCHAR2(20)
) ;
INSERT INTO Religion(religion_no, religion_name) VALUES (10, '기독교');
INSERT INTO Religion(religion_no, religion_name) VALUES (20, '카톨릭교');
INSERT INTO Religion VALUES (30, '불교');
INSERT INTO Religion VALUES (40, '무교');
-- COMMIT은 지금까지 로그버퍼에 저장한 것을 물리적인 테이블에 진짜로 넣은 것
COMMIT;
-- ROLLBACK은 COMMIT을 취소해버리는 것.
ROLLBACK;
--- 다중 행 입력---
--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;
-- 4. Column 추가
-- birth를 DATE라는 데이터 타입으로 컬럼을 추가(ADD)한다.
ALTER TABLE dept30 ADD(birth DATE);
-- 데이터를 넣는다.
INSERT INTO dept30 VALUES(10,'중앙학교', sysdate);
--5 Column 변경
--modify : 컬럼 변경하기
--원래는 dname의 데이터타입이 varchar2(14)인데 9바이트로 변경하는 것이다.
--하지만 dname에 저장돼있는 데이터 중 9바이트를 넘는 12바이트인 '중앙학교'가 있어서 컬럼의 길이를 변경할 수 없다는 오류가 발생한다
-- : "cannot decrease column length because some value is too big"
ALTER TABLE dept30
Modify dname varchar2(9);
-- 12바이트에서 20바이트로 변경. 변경이 잘 된다.
ALTER TABLE dept30
Modify dname varchar2(20);
--6 Column 삭제
ALTER TABLE dept30
Drop Column dname;
--7. TBL 명 변경
--테이블 이름을 dept30에서 dept35으로 변경한다.
RENAME dept30 TO dept35;
--8. TBL 제거
DROP Table dept35;
--9. Truncate 자르기
TRUNCATE table dept_second;
DELETE 와 TRUNCATE 의 비교 (중요 : 별 3개, 면접 단골 문제, 반드시 외우기)
- DELETE, TRUNCATE, DROP 셋 다 데이터를 삭제한다는 공통점이 있다.
- DELETE와 TRUNCATE는 테이블의 데이터만 삭제하는 반면, DROP은 테이블의 정의까지 삭제한다.
- DELETE는 DML이고 TRUNCATE와 DROP는 DDL이다. DML은 COMMIT을 하기 전 버퍼에 저장되기 때문에 작업 속도가 느리고 저장공간을 그대로 유지하지만 DDL은 자동 COMMIT이 되기 때문에 작업 속도가 빠르고 저장공간을 차지하지 않는다.
--테이블 만들기. 대소문자 구별하지 않기 때문에 테이블 이름에 언더바를 넣는 것임.
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(unconditional INSERT ALL) 명령문
-- 서브쿼리의 결과 집합을 조건없이 여러 테이블에 동시에 입력
-- 서브쿼리의 컬럼 이름과 데이터가 입력되는 테이블의 칼럼이 반드시 동일해야 함
INSERT ALL
INTO height_info VALUES(studNo , name ,height)
INTO weight_info VALUES(studNo , name ,weight)
SELECT studno , name , height , weight
FROM student
WHERE grade >= '2';
DELETE height_info;
DELETE weight_info;
-- 학생 테이블에서 2학년 이상의 학생을 검색하여
-- height_info 테이블에는 키가 170보다 큰 학생의 학번, 이름, 키를 입력
-- weight_info 테이블에는 몸무게가 70보다 큰 학생의 학번, 이름, 몸무게를
-- 각각 입력하여라
-- 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;
INSERT ALL
WHEN height > 170 Then
INTO height_info VALUES(studNo , name ,height)
WHEN weight > 70 Then
INTO weight_info VALUES(studNo , name ,weight)
SELECT studno , name , height , weight
FROM student
WHERE grade >= '2';
-- 데이터 수정 개요
-- UPDATE 명령문은 테이블에 저장된 데이터 수정을 위한 조작어
-- WHERE 절을 생략하면 테이블의 모든 행을 수정
--- Update
-- 문1) 교수 번호가 9903인 교수의 현재 직급을 ‘부교수’로 수정하여라
UPDATE professor
SET position = '부교수'
WHERE profno = 9903;
-- 문2) 서브쿼리를 이용하여 학번이 10201인 학생의 학년과 학과 번호를
-- 10103 학번 학생의 학년과 학과 번호와 동일하게 수정하여라
UPDATE student SET (grade, deptno) = (
SELECT grade, deptno
FROM student
WHERE studno = '10103')
WHERE studno = '10201';
-- 데이터 삭제 개요
-- DELETE 명령문은 테이블에 저장된 데이터 삭제를 위한 조작어
-- WHERE 절을 생략하면 테이블의 모든 행 삭제
-- 문1) 학생 테이블에서 학번이 20103인 학생의 데이터를 삭제
--삭제할 때는 기본키를 삭제하는 것을 권장한다.
DELETE
FROM student
WHERE studno = 20103;
-- 문2) 학생 테이블에서 컴퓨터공학과에 소속된 학생을 모두 삭제하여라. HomeWork --> Rollback
delete FROM student
WHERE DEPTNO = (
SELECT deptno
FROM department
WHERE dname = '컴퓨터공학과');
반응형
'프로젝트 기반 JAVA 응용 SW개발 : 22.07.19~23.01.20 > Oracle SQL' 카테고리의 다른 글
8/12 Foreign Key, View, 계층적 질의문, TableSpace (0) | 2022.08.17 |
---|---|
8/11 MERGE, 트랜잭션(원자성, 일관성, 독립성, 지속성), SEQUENCE, 데이터사전, 제약조건, INDEX (0) | 2022.08.16 |
8/9 DeadLock, 독립성, JOIN (0) | 2022.08.10 |
8/8 날짜 출력 형식, DECODE, CASE, GROUP, HAVING, WHERE, 그룹함수, ROLLUP, CUBE (0) | 2022.08.08 |
8/5 Mysql설치 및 사용, Mysql JDBC, order by, 문자 함수, 문자열 길이 반환 함수, 문자조작 함수, 숫자 함수, 날짜 함수 (0) | 2022.08.05 |