Oracle sql_2
Sub-query
- SQL 문안의 또다른 SQL 문 을 가키며 main-query 에 종속적인 관계를 가짐
- 구절의 순서를 바꾸거나, 계산된 값으로 다음 쿼리를 실행할 때 사용
- 사용 시 주의사항
- 반드시 소괄호로 묶어 사용
- 연산자 우항에 작성할 것.
- ORDER BY 문법 지원이 안됨.
- 서브쿼리 위치에 따른 명칭
- SELECT 절에 있는 서브쿼리 : 스칼라 서브쿼리
- FROM 절에 있는 서브쿼리 : 인라인 뷰
- WHERE 절에 있는 서브쿼리 : 서브쿼리
- 유형
- 단일행 단일컬럼
- 다중행 단일컬럼
- 다중열(단일행/다중행)
- 상관
- 스칼라(scala - 단일값)
- inline-view
- 단일 행 서브쿼리: 서브쿼리의 결과가 1행
-- 1. 해당사원 급여, 급여가 a와 동일한 사원 조회 select emp_id, emp_name, salary from employee where salary = ( select salary from employee where emp_name = '윤은해') and emp_name != '윤은해';
- 다중 행 서브쿼리: 서브쿼리의 결과가 여러행
-
in not in: 같은 값 같지않은값 찾음 (단일행 비교연산자 ‘=’과 비슷한용도로 사용) - EXIST : 서브쿼리 값이 있을경우 반환
-- 특정 인물와 같은 직급 사원 조회 select e.emp_name, j.job_name from employee e join job j using(job_code) where job_code in ( select job_code from employee where emp_name in ('차태연','박나라','이오리') );
-
- 다중 컬럼 서브쿼리 : 서브쿼리의 결과가 여러컬럼
- 메인쿼리 WHERE 절과 서브쿼리에서 반환하는 컬럼의 수가 반드시 같아야 함.
- 2개의 컬럼을 반환하는 서브쿼리 사용 시 WHERE 절에도 2개의 컬럼명 적고 괄호로 묶음
SELECT DEPT_CODE, EMP_NAME, SALARY, d.dept_title FROM EMPLOYEE E JOIN DEPARTMENT D ON E.DEPT_CODE = D.DEPT_ID WHERE (E.DEPT_CODE,E.SALARY) IN (SELECT DEPT_CODE, MIN(SALARY) FROM EMPLOYEE GROUP BY DEPT_CODE);
- 상호연관 서브쿼리(상관)
- 메인쿼리의 값을 서브쿼리가 사용하고, 서브쿼리의 값을 받아 메인쿼리가 계산하는 구조
- 각행의 컬럽값이 sub-query 에 필요한경우 유용
- 사용 시 main-query 테이블 별칭 필수
- 잘못 사용될 경우 성능 저하의 원인이 될수있음.
- 일반 서브쿼리와 의 차이점
-
일반 sub-query 는 단독사용하지만, 상관 sub-query 는 main-query 로 부터 값을 전달받아 사용
-- 직급별 평균급여보다 많은 사원을 조회 select emp_name, salary, job_code from employee E where salary > ( select avg(salary) from employee where job_code = E.job_code);
- 메인쿼리에서 직급번호 읽은뒤 서브쿼리로 전달
- 서브쿼리는 메인쿼리에서 받은 직급번호로 평균 급여 계산
- 메인쿼리에서는 서브쿼리의 평균 급여보다 큰 급여의 직원 출력
- 스칼라 : 단일값
- SELECT 절에 오는 서브쿼리로 결과값으로 1행만 반환함.
-- 인턴사원중 최대/최소 급여 사원 포함 select emp_name, nvl(dept_code,'인턴'), salary from employee where(nvl(dept_code,'인턴'), salary) in (select nvl(dept_code,'인턴'), max(salary)from employee group by dept_code) or (nvl(dept_code,'인턴'), salary) in (select nvl(dept_code,'인턴'), min(salary)from employee group by dept_code) order by 2 asc;
- SELECT 절에 오는 서브쿼리로 결과값으로 1행만 반환함.
- INLINE VIEW
- FROM 절에 오는 서브쿼리
- 데이터를 조회하여 가상의 집합을 만들어 조인을 수행 또는 가상의 집합을 다시 조회 시 사용
- INLINE VIEW 안에 또 다른 INLINE VIEW 올수있음
select emp_name,dept_code, gender from (select E.*, decode(substr(emp_no,8,1),'1','남','3','남','여') gender from employee E ) where gender = '여';
JOIN
- 여러 테이블에 흩어진 정보 중 사용자가 필요한 정보만 가져와 가상의 테이블처럼 만들어 결과를 보여주는것
-
조인의 종류
INNER JOIN(교집합)
- 키 값이 있는 테이블의 컬럼 값을 비교 후 조건에 맞는 값을 가져오는 것
- inner join 키워드는 생략 가능함.
- 기준 컬럼의 값이 상대테이블에서 없는 경우, 기준컬럼의 값이 null 인 경우 result set에서 제외됨.
select * from employee E inner join department D on E.dept_code = D.dept_id order by 1;
- EQUI JOIN (동등 조인)
- EQUAL 연산자(=) 를 사용
OUTER JOIN(합집합)
- LEFT OUTER JOIN
- 좌측 테이블의 모든 결과를 가져온 뒤 테이블의 데이터를 매칭하고, 매칭되는 데이터가 없는경우 NULL 을 반환
select * from employee E left outer join department D on E.dept_code = D.dept_id order by 1;
- 좌측 테이블의 모든 결과를 가져온 뒤 테이블의 데이터를 매칭하고, 매칭되는 데이터가 없는경우 NULL 을 반환
- RIGHT OUTER JOIN
- 우측 테이블의 모든 결과를 가져온 뒤 테이블의 데이터를 매칭하고, 매칭되는 데이터가 없는경우 NULL 을 반환
select * from employee E right outer join department D on E.dept_code = D.dept_id order by 1;
- 우측 테이블의 모든 결과를 가져온 뒤 테이블의 데이터를 매칭하고, 매칭되는 데이터가 없는경우 NULL 을 반환
- FULL OUTER JOIN
- 양쪽 모두의 조건이 일치하지 않는 데이터까지 모두 결합해 출력
select * from employee E full outer join department D on E.dept_code = D.dept_id order by 1;
- 양쪽 모두의 조건이 일치하지 않는 데이터까지 모두 결합해 출력
SELF JOIN
- 같은 테이블을 조인
- 테이블에서 자기 자신을 조인시키는것
select A.emp_id, A.emp_name, A.manager_id, B.emp_id, B.emp_name from employee A join employee B on A.manager_id = B.emp_id;
CROSS JOIN(Cartesian Product)
- 조인되는 두 테이블에서 곱집합을 반환(모든 경우의 수를 반환)
select * from employee E cross join department D order by 1;
집합연산자(SET OPERATOR)
- 여러개의 질의결과(결과 집합)를 세로로 연결해서 하나의 가상테이블로 리턴
- 사용 조건
- 컬럼수가 동일해야함.
- 동일 위치의 컬럼은 자료형이 같아야함.
- 컬럼명이 다른 경우 첫번째 컬럼명을 사용
- ORDER BY 절은 맨 마지막에 한번만 사용 가능
- UNION
- 두개의 SELECT 결과를 합침. 합친 결과에서 중복되는 행은 하나만 표시됨.
SELECT NAME,ID FROM MEMBER WHERE NAME LIKE('%길동%') UNION SELECT NAME,ID FROM MEMBER WHERE ID LIKE ('%EW%');
- 두개의 SELECT 결과를 합침. 합친 결과에서 중복되는 행은 하나만 표시됨.
- UNION ALL
- 중복을 제거하지않고 출력
SELECT NAME,ID FROM MEMBER WHERE NAME LIKE ('_길동%') UNION ALL SELECT NAME,ID FROM MEMBER WHERE ID LIKE ('%EW%');
- 중복을 제거하지않고 출력
- INTERSECT
- 서로 중복되는 내용만 출력(교집합)
SELECT NAME,ID FROM MEMBER WHERE NAME LIKE ('_길동%') INTERSECT SELECT NAME,ID FROM MEMBER WHERE ID LIKE ('%EW%');
- 서로 중복되는 내용만 출력(교집합)
- MINUS
- 먼저 위치한 SELECT 문을 기준으로 다른 SELECT 문과 공통된 레코드만 제외한 항목을 추출(차집합)
SELECT NAME,ID FROM MEMBER WHERE NAME LIKE ('_길동%') INTERSECT SELECT NAME,ID FROM MEMBER WHERE ID LIKE ('%EW%');
- 먼저 위치한 SELECT 문을 기준으로 다른 SELECT 문과 공통된 레코드만 제외한 항목을 추출(차집합)
VIEW / 참고사이트,참고사이트2
- 물리적인 테이블에 근거한 논리적인 가상 테이블(여러 테이블에서 원하는값만 가져옴)
- 실제 데이터는 물리적인 테이블에 담겨있지만 테이블처럼 사용 가능함.(실제데이터 없음)
-
물리적인 테이블의 데이터가 변경되면 가상 테이블의 값도 자동으로 변경됨.
- 뷰 생성 쿼리에 함수 사용 시 ALIAS 를 지정
- CREATE VIEW 권한은 RESOURCE 롤에 포함되지 않으므로, 관리자로부터 권한부여가 필요함. ``` – VIEW 권한부여 GRANT CREATE VIEW TO kh;
– 타사용자에게 view 권한 부여 grant select on view_emp to qwerty;
- 뷰 생성
CREATE [OR REPLACE] [FORCE|NOFORCE] VIEW 뷰이름 [(column_aliases)] AS SELECT 문 [WITH READ ONLY] [WITH CHECK OPTION [CONSTRAINT 제약 조건명]]
- [OR REPLACE] : 구문사용 시 DROP 없이 **수정** 가능 - FORCE : 뷰 생성 시 쿼리문의 테이블,컬럼,함수등이 존재하지 않아도 생성 가능 - NOFORCE : 뷰 생성 시 쿼리문의 테이블,컬럼,함수 등이 존재하지 않으면 생성 불가 - COLUMN_ALIASES : SELECT 컬럼의 별칭을 미리 정의 - WITH READ ONLY : SELECT 만 가능(수정,삭제,추가 불가) - WITH CHECK OPTION : WHERE 절의 조건에 해당하는 데이터만 저장,변경 가능
– 뷰 생성 시 함수를 사용할 경우 컬럼 별칭 부여해야 함. CREATE OR REPLACE VIEW VIEW_EMPLOYEE AS SELECT E.EMP_NAME, D.DEPT_TITLE, AVG(E.SALARY) AS AVG_SAL FROM EMPLOYEE E, DEPARTMENT D WHERE E.DEPT_CODE = D.DEPT_ID GROUP BY E.EMP_NAME,D.DEPT_TITLE, SALARY; – 코멘트 추가 comment on column view_employee.dept_title is ‘설명’; – 조회 select * from user_views; – 삭제 DROP VIEW VIEW_EMPLOYEE
- 컬럼 별칭 선언
CREATE OR REPLACE VIEW VIEW_EMPLOYEE ( 이름, TITLE, AVG ) AS SELECT E.EMP_NAME, D.DEPT_TITLE, AVG(E.SALARY) AS AVG_SAL FROM EMPLOYEE E, DEPARTMENT D WHERE E.DEPT_CODE = D.DEPT_ID GROUP BY E.EMP_NAME,D.DEPT_TITLE, SALARY; ```
- FORCE 옵션 추가
- 뷰 생성은 되지만 INVALID 상태로 뷰는 동작하지않음.
CREATE OR REPLACE FORCE VIEW NEW_VIEW AS SELECT EMPNO, EMPNAME FROM EMP;
- 뷰 생성은 되지만 INVALID 상태로 뷰는 동작하지않음.
- WITH CHECK OPTION 옵션
- 해당 옵션 사용 시 INSERT,UPDATE, DELETE 사용 시 WHERE 절의 조건에 해당하는 데이터만 접근 가능
- 제약 조건명 지정 가능함.
WHERE DEPT_CODE ='D5' WITH CHECK OPTION [CONSTRAINT 제약 조건명]
- DML(INSERT,UPDATE,DELECT) 시 주의
- 단순 뷰의 경우 DML 제약 없음(NOT NULL 컬럼 주의)
- 함수, UNION, GROUP BY 등 복합 뷰의 경우 DML 불가능함.(조인만 사용한 경우 제한적으로 가능)
- 생성 및 삭제의 경우 타겟 뷰의 이름이 없을경우 생성, 있을경우 수정함.
-- 생성 및 수정 CREATE OR REPLACE VIEW [스키마.][뷰 NAME] AS SELECT 문; -- 삭제 DROP VIEW [스키마][뷰 NAME] --구조 확인 DESC [스키마][뷰 NAME];
시퀀스(Sequence)
- 시퀀스란 자동으로 순차적으로 증가하는 순번을 반환하는 데이터베이스 객체
- 보통 PK값에 중복값을 방지하기 위해 사용
만약 게시판에 글이 하나 추가될때마다 글번호(PK) 가 생겨야 한다면 하나의 레코드를 넣는 로직을 어딘가에 넣어야하지만 시퀀스를 사용하면 자동으로 추가해주므로 로직이 불필요함.
- 시퀀스 생성
CREATE SEQUENCE [시퀀스명] INCREMENT BY [증감 숫자] -- 시퀀스 증가값(DEFAULT 1) START WITH [시작숫자] -- 시퀀스 시작값 MAXVALUE [최대값] -- 시퀀스 최대값(생략시 무한대) MINVALUE [최소값] -- 시퀀스 최소값(생략시 무한대) CYCLE OR NOCYCLE --기본값 NOCYCLE, CYCLE 로 지정 시 최대값 도달했을때 다시 최소값부터 시작 / MAX/MIN VALUE 도달 시 오류발생 CACHE 숫자 | NOCACHE -- 메모리상에서 시퀀스값 관리, 기본값은 CACHE 20 번호 유실이 문제된다면 NOCACHE 할 것.
- 시퀀스 조회 방법
SELECT * FROM USER_SEQUENCES; --전체 시퀀스 조회 SELECT * FROM USER_SEQUENCES WHERE SEQUENCE_NAME = '생성한시퀀스 명' -- 생성시퀀스 조회 -- 시퀀스 객체의 현재번호 SELECT SEQ_TB_USER_NO.CURRVAL FROM DUAL;
- 시퀀스 수정방법
ALTER SEQUENCE [시퀀스명] INCREMENT BY [증감 숫자] MAXVALUE [최대값] MINVALUE [최소값] CYCLE OR NOCYCLE
- 시퀀스 삭제
DROP SEQUENCE [시퀀스명];
INDEX(색인)
- SQL 조회 구문등에 처리속도 향상을 위해서 테이블 컬럼에 대해 생성하는 객체
- key-value 형식으로 생성, key에는 컬럼값, value 에는 행에 접근할 수 있는 주소값이 저장
-- emp_name 컬럼에 인덱스 추가 create index idx_employee_emp_name on employee(emp_name);
-
검색 속도 향상, 시스템 부하 줄여짐.(table full scan 하지않고 index 먼저 검색 후 행을 조회)
- 인덱스 저장공간 필요, 인덱스를 생성 및 갱신하는데도 부가적인 시간이 필요
- 변경작업(insert, update , delete)이 많다면 실제데이터처리 + 인덱스 갱신 시간이 소요되서, 성능 저하유발 함.
-
- 인덱스 생성시 컬럼 선택 시 고려사항
- 선택도가 좋은 컬럼으로 생성(중복값이 적다는 의미)
- 고유번호를 가지고있는(id,email,name)것들이 선택도가 좋고, 선택도가 나쁜건 성별, null 값이 많은것 등이 선택도가 좋지못함
- pk, uq 제약조건이 걸린 컬럼은 자동으로 인덱스 생성함.
- 인덱스 적용
- WHERE 조건절에 자주 사용되는 컬럼은 인덱스 생성
- JOIN 기준컬럼은 인덱스 생성
- 한번 입력후에 데이터변경이 많지 않은경우
- 데이터가 20만건 이상인 경우
- optimizer 가 index 사용여부 결정하는데 다음경우는 인덱스 사용 안함
- 인덱스 컬럼에 변형이 가해진 경우(substr() 로 변형)
- null 비교
- not 비교
- 인덱스컬럼 자료형과 비교하고자 하는 값의 타입이 다른 경우
-- emp_id 가 문자열로 저장되어있는 상태에서 숫자형 200으로 검색 시 full scan select * from employee where emp_id = 200;