select level, empno, ename, mgr
from emp
start with ename = 'KING'
connect by prior empno = MGR -- PRIOR 자식 = 부모 (순방향 전개)
;
select level, empno, ename, mgr
from emp
start with ename = 'ADAMS'
connect by prior mgr = empno -- PRIOR 부모 = 자식 (역방향 전개)
;
select level, empno, ename, sys_connect_by_path(empno, '/') as 경로, mgr
from emp
start with ename = 'KING'
connect by prior empno = MGR -- PRIOR 자식 = 부모 (순방향 전개)
;
select level, empno, ename, sys_connect_by_path(empno, '/') as 경로, mgr
from emp
start with ename = 'ADAMS'
connect by prior mgr = empno -- PRIOR 부모 = 자식 (역방향 전개)
;
서로 다른 테이블을 참조하는 메인쿼리와 서브쿼리 간에 공통 칼럼이 존재함.
select dname
from dept
where deptno = (select deptno
from emp
where ename = 'SCOTT')
;
select ename, deptno
from emp
where deptno = (select deptno
from emp
where ename = 'SCOTT')
;
select *
from emp
where job = (select job
from emp
where ename = 'SCOTT')
;
select *
from emp
where sal >= (select sal
from emp
where ename = 'SCOTT')
;
select *
from emp
where deptno = (select deptno
from dept
where dname = 'SALES')
;
select *
from emp
where mgr = (
select empno
from emp
where ename = 'KING')
;
select *
from emp
where sal = (select max(sal) from emp)
;
select *
from emp
where deptno in (
select distinct deptno
from emp
where sal >= 3000
)
;
-- 메인쿼리의 비교컬럼 deptno 서브쿼리의 조인조건으로 이동
select *
from emp e
where exists (
select distinct deptno
from emp
where deptno = e.deptno
and sal >= 3000
)
;
차이점:
성능: 두 번째 쿼리(EXISTS
)는 첫 번째 쿼리(IN
)보다 성능이 더 좋을 수 있습니다. EXISTS
는 조건을 만족하는 첫 번째 행을 찾으면 바로 참으로 평가하고 다음 행으로 넘어갑니다. 반면, IN
절은 서브쿼리의 모든 결과를 메모리에 저장하고 메인 쿼리의 각 행과 비교해야 합니다.
중복 제거: 첫 번째 쿼리는 distinct
를 사용하여 중복된 부서 번호를 제거합니다. 두 번째 쿼리에서 exists
는 단순히 해당 조건을 만족하는지 여부만 확인하므로 distinct
가 필요하지 않습니다.
결과적으로 두 쿼리는 동일한 결과를 반환하지만, 데이터베이스의 구현과 데이터의 분포에 따라 성능 차이가 있을 수 있습니다. EXISTS
를 사용하는 두 번째 쿼리가 일반적으로 더 효율적일 가능성이 높습니다.
select *
from emp
where sal in (
select max(sal)
from emp
group by deptno
)
order by deptno
;
select *
from emp
where sal > all (
select sal
from emp
where deptno = 30)
;
select *
from emp
where sal > (
select max(sal)
from emp
where deptno = 30)
;
select *
from emp
where sal > (
select max(sal)
from emp
where job = 'SALESMAN')
;
select *
from emp
where sal > ALL (
select sal
from emp
where job = 'SALESMAN')
;
select *
from emp
where sal > any (
select sal
from emp
where deptno = 30)
;
select *
from emp
where sal > (
select min(sal)
from emp
where deptno = 30)
;
select *
from emp
where sal > (
select avg(sal)
from emp)
and ename like '%S%'
;
select *
from emp, dept
where emp.deptno = dept.deptno
and emp.deptno in (
select distinct deptno
from emp
where sal > (
select avg(sal)
from emp)
and ename like '%S%')
;
select min(hiredate) from emp
;
select min(hiredate)
from emp
where hiredate > (select min(hiredate) from emp);
select *
from emp e, dept d
where e.deptno = d.deptno
and hiredate = (
select min(hiredate)
from emp
where hiredate > (select min(hiredate) from emp))
;
-- Q1
-- scott의 급여에서 1000을 뺸 급여보다 적게 받는 사원
select ename, sal
from emp
where sal < (
select sal
from emp
where ename = 'SCOTT') - 1000
;
-- Q2
-- job이 manager인 사원들 중 최소급여를 받는 사원보다 급여가 적은 사원
select ename, sal
from emp
where sal < (
select min(sal)
from emp
where job = 'MANAGER')
;
-- Q3
-- WARD가 소속된 부서 사원들의 평균 급여보다, 급여가 높은 사원
select ename, sal
from emp
where sal > (
select avg(sal)
from emp
where deptno = (
select deptno
from emp
where ename = 'WARD'))
;
-- Q4
-- 이름에 K가 들어가는 사원들 중 가장 급여가 적은 사원
select min(sal)
from emp
where ename like '%K%';
select *
from emp, dept
where emp.deptno = dept.deptno
and sal = (
select min(sal)
from emp
where ename like '%K%')
;
-- Q5
-- 두 번째로 많은 급여를 받는 사원의 이름과 급여
select max(sal)
from emp
;
select max(sal)
from emp
where sal < (select max(sal) from emp)
;
select ename, sal
from emp
where sal = (
select max(sal)
from emp
where sal < (select max(sal) from emp))
;
-- Q6
-- 커미션을 받는 부서명 출력
select distinct dname
from emp, dept
where emp.deptno = dept.deptno
and comm is not null
;
-- 커미션을 받는 부서명 출력(EXISTS 사용)
select distinct dname
from dept
where exists (
select *
from emp
where emp.deptno = dept.deptno
and emp.comm is not null
);
-- Q7
-- 최고 급여를 받는 사원과 같이 근무하는 모든 사원
select max(sal)
from emp
;
select deptno
from emp
where sal = (select max(sal) from emp)
;
select *
from emp
where deptno = (
select deptno
from emp
where sal = (select max(sal) from emp))
;
create table emp01_tbl (
empno number(4),
ename nvarchar2(20),
sal number(7, 2),
jumin char(13),
hiredate date,
resume clob
);
create table emp02
as
select * from emp;
create table emp06
as
select * from emp where 1=0;
desc emp01;
alter table emp01
add (job varchar2(9))
;
desc emp01;
alter table emp01
modify (job varchar2(30))
;
desc emp01;
alter table emp01
drop (job)
;
desc emp01;
alter table emp01
rename column ename to emp_name
;
desc emp01
;
-- 테이블 이름 변경
alter table emp01
rename to emp01_tbl
;
-- 테이블 삭제
drop table emp01;
-- 모든 행 삭제. 테이블은 미삭제
truncate table emp01;
-- comment 작성
comment on column emp01.empno is '사번';
create table 점수 (
학번 char(4),
국어 number(3),
수학 number(3)
)
;
alter table 점수
rename to score
;
alter table score
rename column 학번 to hakbun
;
alter table score
rename column 국어 to kor
;
alter table score
rename column 수학 to math
;
comment on column score.hakbun is '학생번호';
comment on column score.kor is '국어점수';
comment on column score.math is '수학점수';
-- 영어 칼럼 추가
alter table score
add (eng number(3))
;
comment on column score.eng is '영어점수';
-- 중간/기말점수 상태구분코드 컬럼 추가
alter table score
add (div char(1))
;
-- 학번 컬럼 유형 변경
alter table score
modify (hakbun char(6))
;
-- DD
select * from user_tables
order by table_name;
-- dept 테이블의 구조만 복사. 데이터는 복사하지 않음
create table dept01
as
select * from dept where 1=2
;
-- 데이터 추가
insert into dept01 (deptno, dname, loc)
values (10, 'ACCOUNTING', 'NEW YORK')
;
insert into dept01
values (40, 'OPERATIONS', NULL)
;
-- dept 테이블의 행을 복사
insert into dept01
select * from dept
;
create table emp_test01
as
select * from emp
;
update emp_test01
set hiredate = add_months(sysdate, -1)
where to_char(hiredate, 'yy') = 82
;
select * from emp_test01
order by hiredate desc;
delete from dept01
where deptno = 40;
select * from dept01;
create table 날짜 (
입사일 date
)
;
insert into 날짜 values('20180507'); -- ok
insert into 날짜 values('2018-05-07'); -- ok
insert into 날짜 values('2018/05/07'); -- ok
insert into 날짜 values('2018/05/07 12:24:00'); -- 에러 발생
insert into 날짜 values
(to_date('2018/05/07 12:24:00', 'yyyy/mm/dd hh24:mi:ss')); -- to_date로 형 맞추기
다시 SCOTT 제거 시도하면 lock 발생
commit 수행하기
lock이 풀리며 성공적으로 delete 수행됨
--도서
CREATE TABLE BOOK (
bno NUMBER(3) NOT NULL,--도서번호
bname VARCHAR2(20) NOT NULL,--도서명
bdesc VARCHAR2(4000),--도서설명
bprice NUMBER--가격
);
INSERT INTO BOOK VALUES (101 ,'오라클1', '기본',1000);
INSERT INTO BOOK VALUES (102 ,'오라클2', '기본',2000);
INSERT INTO BOOK VALUES (201 ,'자바1', '기본',2000);
--회원
CREATE TABLE MEM(
MEMID VARCHAR2(20) NOT NULL,--회원아이디
MEMNAME VARCHAR2(20),--회원명
MEMADDR VARCHAR2(20)----회원주소
);
INSERT INTO MEM(MEMID ,MEMNAME ,MEMADDR )
VALUES('hong','홍길동','서울');
INSERT INTO MEM(MEMID ,MEMNAME ,MEMADDR )
VALUES('lee','이순신','서울');
--주문
CREATE TABLE BORDER(
-- 주문번호(1,2,.. 일련번호)
ONO NUMBER NOT NULL,
-- 주문도서번호
BNO NUMBER ,
--주문자ID
MEMID VARCHAR2(20),
--주문도서수량
OQTY NUMBER
);
--- Q1
-- 홍길동이 도서번호 101인 도서 2권 주문
insert into border
values (1, 101, 'hong', 2);
select * from border;
--- Q2
-- 이순신이 도서번호 201인 도서 3권 주문
insert into border
values (2, 201, 'lee', 3);
select * from border;
--- Q3
-- 이순신의 주문도서수량을 5권으로 수정
update border
set oqty = 5
where ono = (
select ono
from border
where memid = 'lee'
)
;
select * from border;
--- Q4
-- 김유신이 회원가입 후 도서번호 201인 도서 1권 주문
insert into mem
values ('kim', '김유신', '부산');
select * from mem;
insert into border
values (3, 201, 'kim', 1);
select * from border;
--- Q5
-- 주문한 회원명 및 도서명을 주문수량과 함께 출력
-- 단, 주문테이블 기준으로 세개 테이블 연결조인
select * from book; -- bno, bname, bdesc, bprice
select * from mem; -- memid, memname, memaddr
select * from border; -- ono, bno, memid, oqty
select memname, bname, oqty
from book, mem, border
where border.bno = book.bno
and border.memid = mem.memid
;
--- Q6
-- 도서번호별로 주문한 총 도서수량 출력
select *
from book, mem, border
where border.bno = book.bno
and border.memid = mem.memid
;
select border.bno, sum(oqty)
from book, mem, border
where border.bno = book.bno
and border.memid = mem.memid
group by rollup(border.bno)
order by bno
;
create table emp02 (
empno number(4) constraint emp05_empno_pk primary key,
email varchar2(50) not null unique,
ename varchar(2) not null,
job varchar2(9),
deptno number(2) not null
);
insert into emp02
values (1, 'A', 'A', 'SALESMAN', 10); -- insert 수행
insert into emp02
values (1, 'A', 'A', 'SALESMAN', 10); -- insert 한번 더 수행 시 에러 발생
create table dept06 (
deptno number(2) primary key,
dname varchar2(20) not null,
loc varchar2(20)
);
insert into dept06
select * from dept
;
create table emp06 (
empno number(4) constraint emp06_empno_pk primary key,
ename varchar2(10) constraint emp_ename_nn not null,
job varchar2(9),
deptno number(2) constraint emp06_deptno_fk references dept06(deptno)
)
;
insert into emp06
values (7566, 'JONES', 'MANAGER', 30); -- ok
insert into emp06
values (7567, 'JONES2', 'MANAGER', 50); -- not ok
떼껄룩~ 이번주도 화이팅합시다