Notice
Recent Posts
Recent Comments
Link
«   2025/07   »
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
Archives
Today
Total
관리 메뉴

parisangsoo

DB 03/10 본문

DB

DB 03/10

SangssI 2023. 3. 10. 10:25

SUBQUERY : SELECT 문장 안에 SELECT문장이 중첩되어 있는 형태

여러번의 DB접속이 필요한 상황을 한번으로 줄여 속도증가에 도움을 줄수 있다.

-- 서브쿼리를 사용할 수 있는 영역
-- 1) where, having절
-- 2) select나 delete의 from절
-- 3) update의 set절
-- 4) insert의 into절

 

--예) 사원테이블에서 이름이 'MIchael'이고, 직종이 MK_MAN인 사원의 급여보다 초과해서 받는
       사원들의 정보를 사번,이름,직종,급여 순으로 출력

 

subquery를 사용하지 않을때

--문제접근1) 이름이 마이클이고 직종이 MK_MAN인 사원의 급여 
SELECT salary
FROM employees
WHERE first_name = 'Michael' AND job_id = 'MK_MAN';  --결과 : 13000


--문제접근2) 접근1을 통해 얻은 급여값 13000을 초과하는 직원들을 조회
SELECT employee_id, first_name, job_id, salary
FROM employees
WHERE salary > 13000;   -- 최종 결과

subquery를 사용하였을때

-- 위의 두가지 select문을 subquery를 통해 하나로 통합

SELECT employee_id, first_name, job_id, salary
FROM employees
WHERE salary > ( SELECT salary
	         FROM employees
                 WHERE first_name = 'Michael' AND job_id = 'MK_MAN' );

--문제1) 사원테이블에서 사번이 111번인 사원의 직종과 같고,
사번이 159번인 사원의 급여를 초과한 사원들의 정보를 
사번,이름,직종,급여 순으로 출력 

SELECT employee_id, first_name, job_id, salary
from employees
where  -- 서브쿼리가 2개 필요함
job_id = ( select job_id from employees where employee_id = 111)
and
salary > ( select salary from employees where employee_id = 159);

--문제2) 사번이 150인 사원의 급여와 같은 급여를 받는 사원들의 사번,이름,급여를 출력

SELECT employee_id, first_name, salary
FROM employees
WHERE salary = (SELECT salary FROM employees WHERE employee_id = 150);

--문제3) 월급이 평균 월급 이상인 사원들의 이름과 급여를 출력

SELECT first_name, salary
FROM employees
WHERE salary >= (SELECT avg(salary) FROM employees)
ORDER BY salary;


--문제4) Bruece와 같은 부서에서 근무하고 있는 사원들의 이름과 , 부서번호를 출력

SELECT first_name, department_id
FROM employees
WHERE department_id = (SELECT department_id FROM employees WHERE first_name = 'Bruce')
ORDER BY first_name;

--문제5) 137번 사원의 급여이상이며, 149번 사원의 급여 이하인 사원들의 이름과 급여를 조회

SELECT first_name, salary
FROM employees
WHERE salary between ( SELECT salary FROM  employess WHERE employee_id = 137) -- 이상,이하이므로 between연산자 사용
AND
(SELECT salary FROM  employess WHERE employee_id = 149);

--문제6)  직종과 직종별 평균 급여를 조회하되, 평균급여가 Bruce 사원의 급여를 초과하는 경우만 조회

SELECT job_id, avg(salary)  -- 일반컬럼과 그룹함수가 같이 쓰이므로 GROUP BY 사용
FROM employees
GROUP BY job_id      -- 평균급여(AVG(SALARY),그룹함수)를 조건식으로 쓰므로 WHERE이 아닌 HAVING
HAVING avg(salary) > (select salary FROM employees WHERE first_name = 'Bruce') -- 그룹함수의 조건은 where사용 불가, having 사용
ORDER BY job_id

--문제7) 사원 테이블에서 급여가 가장 적은 사원의 사번, 이름, 급여를 출력

SELECT employee_id, first_name, salary
FROM employees
WHERE salary = (SELECT MIN(salary) FROM employees); -- 가장 적은 급여를 구해야함

 


문제 8) 
사번이 158번인 사원과 직종이 같고, 급여가 164번 사원 초과인 사람들의 사번, 이름 ,직종, 급여를 출력

SELECT employee_id, first_name, job_id, salary
FROM employees
WHERE job_id = (SELECT job_id FROM employees WHERE employee_id = 158)
AND
salary > (SELECT salary FROM employees WHERE employee_id = 164)
ORDER BY employee_id;

--문9)
사원테이블에서 직종이 SA_REP인 사원의 최소 급여보다 적으면서(미만)
직종이 SH_CLERK이 아닌 사원들의 이름과,직종, 급여를 출력

SELECT first_name, job_id, salary
FROM employees
WHERE salary < (SELECT MIN(salary) FROM employees WHERE job_id = 'SA_REP')
AND
job_id != 'SH_CLERK';


--문10)
사원테이블에서 100번 부서의 최소급여를 초과하는 다른 모든 부서의 번호와, 최소 급여를 출력

SELECT department_id, MIN(salary)
FROM employees;
GROUP BY department_id
HAVING MIN(salary) > (SELECT MIN(salary) FROM employees WHERE department_id = 100);


--문11)
사원 테이블에서 last_name중에 'Bat'라는 단어를 포함하고 있는 사원과 같은 부서에서 근무하는 사원의
사번, 부서번호, 이름을 출력

SELECT  employee_id, department_id, first_name
FROM employees
WHERE department_id = (SELECT department_id FROM employees WHERE last_name LIKE '%B%');

TRANSACTION : DB의 상태를 변화시키기 위해 수행하는 작업의 단위
(INSERT, DELETE, UPDATE 구문에만 허용)

1. ROLLBACK 키워드 (commit; 을 실행하기 전의 실수일때)

-실수로 잘못 작성된 쿼리문이 있거나 전달이 정상적으로 전달되지 않은 쿼리 문이 있는 경우
 commit; 단계를 거치지 않았을때  rollback;을 통해 직전단계로 돌아갈수 있다.

 

예제)

CREATE table EMPL  -- employees테이블의 전체내용을 복사하여 EMPL 테이블 생성
AS select * from employees;

--전체 테이블 수 출력
SELECT COUNT(*) from employees;

--사번이 100번인 사원을 삭제 , -- commit;은 진행하지 않음
DELETE 
FROM empl
WHERE employee_id = 100;

--하지만 위의 삭제코드에서 commit을 하지 않아도
내부적으로는 삭제 쿼리문이 실행중

--EMPL테이블의 데이터를 수정

UPDATE empl SET first_name = 'A'; -- 모든사원의 이름을 A라고 실수로 수정 

rollback; -- 100번인 사원과 A로 이름이 바뀐 실수 모두 전으로 롤백(commit;이 진행되지 않았기 때문에)

--만약 위의 코드처럼 실수로 잘못작성된 쿼리문이 있거나 전달이 정상적으로 전달되지않은 쿼리문이 잇는 경우 rollback; 키워드를 통해 commit; 직전단계까지 돌아 갈수 있다,

2. TIMESTAMP 키워드 (commit; 을 실행한 후의 실수일때)

UPDATE empl SET first_name = 'B';  --전체의 이름을 'B'로 수정했을때의 실수
commit;  -- commit과정까지 실행하여 데이터가 업데이트 완료 되었음.

--위의 코드처럼 commit 이 진행된(코드실수로 데이터가 바뀐) 이후에 이전단계로 rollback을 원한다면?

1) EMPL -- 실수한 empl의 테이블의 데이터를 삭제 한다.
DELETE FROM empl;  -- 테이블 empl의 모든 데이터 삭제

2) rollback을 원하는 시간대로 돌아가서 테이블을 재 조회
INSERT INTO empl  -- empl 테이블에 데이터 추가 
SELECT * FROM empl
as of timestamp(systimestamp-interval '10' minute)  -- 실제로 데이터가 추가 된게 아니라 데이터를 조회만 하고 있음
commit; -- 10분전의 empl데이터를 가져와 다시 새로운 empl의 테이블에 내용을 추가한다. 


as of timestamp(
	systimestamp-interval '원하는 시간' 단위);
-- '1' minute : 1분전
-- '2' hour :  2시간전
-- '3' day : 3일전

SEQUENCE : 중복되지 않는 연속적인 번호를 만들어주는 키워드(시퀀스)(primary key)

-- 형식
   create sequence 시퀀스명  -- 이거하나만 알고 넘어가도 됨 *** 중요
   start with 시작값( 기본값 1 )
   increment by 증가값( 기본값 1 )
   maxvalue 최대값 
   minvalue 최소값;
   cache / nocache (시퀀스의 속도를 위한 캐시사용 여부);

 

EX)

goods테이블 생성
create table goods(
no NUMBER(3) primary key, --기본키가 되면서 절대로 중복된 값이 들어갈 수 없다
name varchar2(200) unique -- 기본키가 존재하지만 중복된 값이 들어갈수 없게 unique 속성 지정
);

 

--굿즈 테이블에서 사용할 시퀀스 지정 
create sequence goods_no_seq;      -- goods테이블의 no 컬럼(primary key) 시퀀스

 

--데이터 추가
insert into GOODS values(goods_no_seq.nextVal,'라이언');   --   no = 1
insert into GOODS values(goods_no_seq.nextVal,'춘식이');   --  no = 2
inser into GOODS values(3,'춘식이2');      --  no = 3 -- 시퀀스를 사용할때는 강제로 3 값을주고 추가하면 절대 안된다. 대신 빈 공간에는 가능
insert into GOODS values(goods_no_seq.nextVal,'무지');      -- no = 3 시퀀스는 현재 2까지 증가되어 있는 상태고 3의 값이 와야하는데 위 코드에서 강제로 3을 값을 주어 값이 중복되기 때문에 오류
commit;

 

시퀀스를 사용할때  no 빈공간이 생기는 경우
시퀀스를 사용하여 쿼리문을 넣을때 '값이 중복되는 오류'(데이터 측면의 오류)가 나서 데이터가 들어가지 않아도 시퀀스는 증가한다.
하지만 쿼리문의 오타로인한 문법적인 오류는 시퀀스가 증가하지 않는다.
즉 insert into GOODS values(goods_no_seq.nextVal,'무지');    에서 시퀀스의 값이 3으로 증가하여 쿼리문을 작성하고 오류가 나면 값이 들어가지 않지만 시퀀스는 4로 증가하여 수정하고 쿼리문을 넣으면 no은 4로 들어가게된다.
이때 3은 빈공간이므로 강제적으로 시퀀스가 아닌 no=3을 넣는경우엔 오류가 나지 않는다.

 

캐시사용 여부의 차이

nocache를 사용한 시퀀스는 미리 데이터가 들어갈 공간을 마련해두지 않는다.

--------------------
no        name
1  라이언
2 춘식이
3 무지
4 콘
5 어피치

cache를 사용한 시퀀스는 미리 데이터가 들어갈 공간을 20개를 마련해 둔다. 공간할당에 유리함.
-------------------
no name
1 라이언
2 춘식이



20

'DB' 카테고리의 다른 글

이클립스와 DB연동을 통한 개발환경 설정  (0) 2023.03.14
DB 03/13  (0) 2023.03.13
DB 03/09  (0) 2023.03.09
DB 03/08  (0) 2023.03.08
DB 03/07  (1) 2023.03.07
Comments