-- UNION : 중복데이터가 조회되지 않음, PK가 있다면 정렬해서 보여줌-- emp : 미국본사, cp_emp3 : 한국지사라 가정했을 때-- 미국본사와 한국지사 연봉이 2000이하인 사원급여를 올려주고 싶어-- 2000이하인 사원의 사원번호, 사원명, 연봉, 직무를 조회SELECT empno, ename, sal, jobFROM empWHERE sal <= 2000UNIONSELECT empno, ename, sal, jobFROM cp_emp3WHERE sal <=2000;-- cp_emp3에 emp테이블에서 30번 부서 사원정보를 모두 추가INSERT INTO cp_emp3(empno, ename, deptno, sal, job)(SELECT empno, ename, deptno, sal, job FROM emp WHERE deptno=30);-- UNION ALL : 중복데이터가 조회됨, 정렬 안된채로 조회SELECT empno, ename, sal, jobFROM empWHERE sal <= 2000UNION ALLSELECT empno, ename, sal, jobFROM cp_emp3WHERE sal <=2000;-- 컬럼의 갯수가 일치하지 않으면 에러SELECT empno, ename, salFROM empWHERE sal <= 2000UNIONSELECT empno, enameFROM cp_emp3WHERE sal <= 2000;
-- 데이터형이 일치하지 않으면 에러SELECT empno, ename, salFROM empWHERE sal <= 2000UNION ALLSELECT empno, ename, jobFROM cp_emp3WHERE sal <=2000;
INTERSECT
교집합
서로다른 테이블의 중복된 값을 조회
사용방법은 UNION과 같음
-- 미국본사의 사원정보와 한국지사의 사원정보 중 일치하는 정보만 조회SELECT empno, ename, sal, jobFROM empWHERE sal <= 2000INTERSECTSELECT empno, ename, sal, jobFROM cp_emp3WHERE sal <=2000;
MINUS
차집합
상위 SELECT 조회된 결과에서 하위 SELECT의 결과를 뺀 결과를 조회
조회되는 테이블의 순서가 중요!
상위 SELECT는 레코드의 수가 하위 SELECT 레코드 수보다 많아야 한다
-- MINUS : 상위 SELECT에서 조회된 결과에서 하위 SELECT에서 조회된 결과를 뺀 나머지를 조회SELECT empno, ename, sal, jobFROM empMINUSSELECT empno, ename, sal, jobFROM cp_emp3WHERE sal <=2000;
JOIN
서로 다른 테이블을 합쳐 조회할 때 사용
옆으로 붙는다
ANSI 쿼리 지원(길다), Oracle 쿼리 지원
INNER JOIN, OUTERJOIN, CROSS JOIN, SELF JOIN 존재
ORACLE 문법은 FULL OUTER JOIN을 지원하지 않는다(ANSI로만 가능)
EQUI JOIN, NON EQUI JOIN 두가지 형태로 사용
조인조건을 잘못 설정하면 **카티션프로덕트(Cartesian Product)**가 발생하고 나온 결과를 사용할 수 없다
DRIVING TABLE 선정에 따라 결과가 나오는 속도가 달라짐
DRIVING TABLE : 조인되는 키로 사용되는 테이블
INNER JOIN
조인하는 모든 테이블에 동일한 값이 있는 것만 조회
EQUI JOIN/ NON EQUI JOIN은 조인조건에 따라 결정됨
-- 테이블간 같은 이름의 컬럼이 없으면 그냥 컬럼명으로 조회 -> 어느 테이블의 컬럼인지 확인이 힘들어 권장하지 않음! -- 테이블간 같은 이름의 컬럼명이 있을 땐 테이블명.컬럼명 으로 조회-- 테이블명이 길다면 alias 붙일 수 있다 - 권장-- 테이블은 8개 이상 조인하지 않는다(엄청 느려짐)-- ANSI INNER JOINSELECT 테이블1.컬럼명, 조인할테이블.컬럼명, ...FROM 테이블1 aliasINNER JOIN 조인할테이블 alias ON 조인조건;-- Oracle INNER JOINSELECT 테이블1.컬럼명, 조인할테이블.컬럼명,...FROM 테이블1 alias, 조인할테이블 aliasWHERE (조인조건) AND 검색조건
-- 사원번호, 사원명, 부서번호, 부서명, 부서위치, 연봉 조회-- ANSI INNER JOINSELECT e.empno, e.ename, e.deptno, d.dname, d.loc, e.salFROM emp eINNER JOIN dept d ON e.deptno = d.deptno;-- ORACLE INNER JOINSELECT e.empno, e.ename, e.deptno, d.dname, d.loc, e.salFROM emp e, dept dWHERE e.deptno=d.deptno;
DRIVING TABLE 선정
DRIVING TABLE을 잘 정하면 많은 양의 데이터를 가져올 때 속도가 빠름
DRIVING TABLE : 조인되는 키로 사용되는 테이블
PK와 FK의 관계가 있을 때
PK가 DRIVING TABLE이 되면 좋다
관계가 없는 테이블을 조회할 때
레코드가 적거나, 레코드의 다양성이 적은 컬럼이 DRIVING TABLE로 선정되는게 좋다.
SELECT e.empno, e.ename, e.deptno, d.dname, d.loc, e.salFROM emp eINNER JOIN dept d ON e.deptno = d.deptno;
d.deptno(PK), e.deptno(FK)
'=' 오른쪽이 key, 얘를 기준으로 같은걸 뽑아냄
검색시 사용되는게 KEY
예) e.deptno=d.deptno
d.deptno 10, 20, 30, 40. 4개의 레코드
10을 갖고 e.dept와 비교, 20을 갖고 비교, 30을 갖고 비교, 40을 갖고 비교
레코드 수 만큼 4번 비교
예) d.deptno=e.deptno
e.deptno가 키가 되면 20,10,20,10,30,20,10,... 이런식으로 14개의 레코드
20가져와서 d.dept와 비교, 10갖고 비교, 20갖고 비교, ...
레코드 수 만큼 14번 비교
결국 레코드의 수 만큼 비교를함
DRIVING TABLE로 레코드가 적은 테이블을 '키'로 선정해야 검색 속도가 빨라진다!
OUTER JOIN
어느 한 쪽에만 레코드가 있어도 조인결과를 보여줄 때 사용
LEFT OUTER JOIN, RIGHT OUTER JOIN, FULL OUTER JOIN이 존재
ORACLE JOIN 문법은 FULL OUTER JOIN을 지원하지 않음
레코드의 구조를 잘 알아야 원하는 결과를 얻을 수 있음
-- ANSISELECT 컬럼명, 테이블명.컬럼명, alias.컬럼명, ...FROM 테이블명LEFT OUTER JOIN 조인할테이블명 ON 조인조건--RIGHT OUTER JOIN / FULL OUTER JOIN 바꿔서 사용할 수 있음-- LEFT, RIGHT로 모두 보고 싶은 테이블(데이터가 있는 방향을) 설정-- ORACLE-- 조인조건에 레코드가 없는 테이블에 (+)를 붙여줌-- FK에 붙여주면 됨-- 조인조건 양쪽에 (+)를 붙이면 error 발생SELECT 컬럼명, 테이블명.컬럼명, alias.컬럼명, ...FROM 테이블명 alias, 테이블명2 alias, ...WHERE alias.컬럼명(+) = alias.컬럼명;
-- OUTER JOIN : 어느 한쪽 테이블에만 레코드가 존재하더라도 조회-- 모든 부서의 부서번호, 부서명, 사원번호, 사원명, 입사일 조회-- ANSI) LEFT나 RIGHT를 쓰되 레코드가 있는 쪽 테이블을 지정-- 레코드의 구조를 잘 모른다면 FULL OUTER JOIN을 하여 양쪽 테이블 모두 조회가능SELECT d.deptno, d.dname, e.empno, e.ename, e.hiredateFROM dept dLEFT OUTER JOIN emp e ON e.deptno = d.deptno;-- ORACLE) SELECT d.deptno, d.dname, e.empno, e.ename, e.hiredateFROM dept d, emp eWHERE e.deptno(+) = d.deptno;
-- 사원테이블에서 'SCOTT'인 사원보다 연봉을 작게 받는 사원의-- 사원번호, 사원명, 입사일, 연봉을 조회-- 서브쿼리를 사용하는 방법SELECT empno, ename, hiredate, salFROM empWHERE sal < (SELECT sal FROM emp WHERE ename='SCOTT');-- SELF JOIN을 사용하는 방법-- 테이블 한개는 조회용으로만, 또다른 테이블은 비교(조건)용SELECT e1.empno, e1.ename, e1.hiredate, e1.salFROM emp e1, emp e2WHERE (e1.sal < e2.sal) AND e2.ename='SCOTT';
-- 조인한 복수행 서브쿼리로 얻어진 결과(INLINE VIEW)를 조회할 땐 컬럼명을 그냥 쓴다SELECT ename, sal, dnameFROM(SELECT e.ename, e.sal, d.dname FROM emp e, dept d);
SEQUENCE
증가하는 수를 반환하는 객체
user_sequences 딕셔너리에서 시퀀스를 조회가능
nextval, currval 가상 컬럼(pseudo column) 사용
nextvar
File 영역에 존재하는 번호를 Server Instance 영역에 올리고 현재번호의 다음 번호를 얻는 일을 함
currval
Server Instance 영역에 존재하는 시퀀스의 현재번호를 얻는 일을 함
Server Instance에 sequence가 올라와 있지 않으면 error 발생
nextvar이 먼저 사용되고 사용되어야 됨
서버가 종료되면 일정개수의 수(CACHE)를 잃어버림
기본적으로 20개
쿼리문이 실행 실패하더라도 번호는 소진됨
순차적인 번호를 얻을 순 있지만 넣을 순 없다.
증가하는 수를 가지고 PK를 사용해야할 때 좋음
생성
CACHE - 메모리에 올려놓을 수(기본 20개)
CYCLE은 끝값까지 사용하면 처음부터 반복실행할 것인지 결정(NO CYCLE이 기본)
CREATE SEQUENCE 시퀀스명 INCREMENT BY 증가값 START WITH 시작값 MAXVALUE 끝값 CACHE 메모리에올려놓을수 CYCLE[NOCYCLE]
사용
시퀀스명.nextval시퀀스명.currval
-- SEQUENCE : 순차적으로 증가하는 수를 사용하는 객체-- 1에서부터 9999999까지 1씩 증가하는 시퀀스를 생성CREATE SEQUENCE seq_test INCREMENT BY 1 START WITH 1 MAXVALUE 999999;
-- nextval 안하고 먼저 currval 사용하면 error!-- currval은 메모리에 올라와 있는 시퀀스의 현재 번호를 얻는 일을 함SELECT seq_test.currvalFROM DUAL;-- 서버가 종료되면 메모리에 존재하던 시퀀스는 사라짐-- 정의된 LAST_NUMBER부터 시작
-- 쿼리문의 실행 실패에도 시퀀스는 사라진다INSERT INTO cp_emp(empno, ename, hiredate, sal)VALUES(seq_test.nextval, '안기모씨', SYSDATE, 300);-- ename의 크기가 10이라 한글4글자가 안들어감, 위에 INSERT 쿼리 여러 시도 후 (실패)-- 제대로 넣으면 실패한 만큼 시퀀스 수가 올라가 있는걸 확인 가능하다