현 블로그는 모바일 환경이 아닌 PC환경에 최적화 되어있습니다.

 Mir의 운영환경

이전 Chapter에서 테이블의 생성 및 수정, 삭제하는 DDL에 대해 알아보았다.
이번 Chapter에서는 만들어진 테이블내에 DML(데이터 조작어)를 이용하여 데이터를 추가, 수정, 삭제까지 해보도록 하자.

DML이란 스키마 객체의 데이터를 입력(INSERT), 수정(UPDATE), 조회(SELECT), 삭제(DELETE)를 하거나
테이블의 잠금(LOCK TABLE), SQL문의 처리에 대한 정보입수(EXPLAIN PLAN), PL/SQL 모듈을 호출(CALL)등을 수행하는 문장의 집단이다.

각 명령어는 INSERT, UPDATE, DELETE, SELECT, LOCK TABLE, EXPLAIN PLAN, CALL등으로 시작하는데
우선 이번 Chapter에서는  INSERT(입력), UPDATE(수정), DELETE(삭제), MERGE(합병)를 알아보자.


INSERT(입력)
INSERT문으로 데이터를 추가할때에는 
" INSERT INTO 테이블명 [컬럼명] VALUES [값] "
의 형식으로 사용하며 컬럼명을 생략할수도 있는데 생략할 경우에는 컬럼순서대로 값을 넣어주면된다.
그럼 우선 테이블에 데이터를 입력하기 전에 dept테이블의 모든 값을 복사하여 test1이라는 연습용 테이블을 생성해보자. 
테이블 생성하는 방법을 벌써 까먹으면 안된다!! (말해놓고 필자는 왠지 양심에 찔린다;;)


CREATE TABLE test1

AS select * from dept;

 



dept테이블을 복사한 test1이라는 테이블을 생성하였다.
자 그러면 이제 INSERT문을 사용하여 테이블에 데이터를 추가시켜보자.
test1테이블에 SEOUL에 있는 50번 부서 DESIGN부서를 테이블에 추가시켜보도록 하자. 


INSERT INTO test1(deptno, dname, loc)
VALUES (50, 'DESIGN', 'SEOUL');
 
 

test1테이블의 deptno, dname, loc 컬럼에 값(VALUES)을 50, SEOUL, DESIGN을 추가시켜라는 명령이다.
하나의 로우값이 생성되었다고 뜬다. select로 test1의 모든값을 살펴보도록 해보자.

 test1테이블의 부서가 하나더 추가된것이 확인된다. 


INSERT문을 사용할때 주의할점들이 몇가지 있다.

1. 컬럼명에 기술된 컬럼수와 VALUES 다음에 나오는 값의수는 일치해야된다.

test1(deptno, dname, loc) 처럼 3개의 컬럼명을 적었을경우 값 또한
VALUES(50, 'DESIGN', 'SEOUL') 처럼 3개의 값을 적어주어야 한다. 
만약 추가할 값이 없으면 컬럼명을 빼던지 아니면 값에 NULL값을 주어야한다. 

2. 지정한 테이블내의 컬럼명을 확인해야한다.
당연한 소리지만 지정한 테이블(test1)안에 있는 컬럼명이 아니거나 
오타가 나게 되면 오류가 발생한다.

3. 각 컬럼의 데이터타입에 맞는 값을 넣어주어야 한다.
deptno컬럼에는 숫자형 값(50) dname컬럼에는 문자형 값(DESIGN)을 넣어주어야 되는것이다.
문자형값은 ' '(홑따옴표)로 감싸주어야지 문자형으로 인식한다.
각 컬럼의 데이터타입을 볼려면 desc를 사용하면 된다. 


4. 컬럼명의 나열 순서대로 값을 추가시켜주어야 한다.

만약 test1(dname, deptno, loc)의 순서로 컬럼을 지정해주면
값 또한 DESIGN
(dame), 50(deptno), SEOUL(loc)순으로 적어주어야 한다.

5. 컬럼명을 기술하지 않았을때에는 컬럼의 순서대로 모든 값을 다 넣어주어야 한다.
INSERT INTO test1
VALUES( 50, 'DESIGN', 'SEOUL')

위와 같이 test1테이블을 지정한뒤에 컬럼명을 기술하지 않았을때는 컬럼의 출력순서대로 모든 값을 지정해 주어야 한다.
값을 하나라도 적게 입력하면 오류가 나게 된다.
(컬럼명을 기술하지 않았을때는 컬럼의 순서대로 모든 컬럼을 지정해준거와 같은 효과를 가지고 있다.) 
출력순서는 desc를 이용하여 조회했을때 보여지는 컬럼의 순서이다.

6.NULL값을 입력할때에는 컬럼이 NULL값을 허용하는지 확인해봐야된다.
마찬가지로 desc를 이용하면 null값을 허용하는지 불허 하는지 알아볼수 있다.
null?에 not null이라고 설정되어 있으면 그 값은 꼭 적어줘야 한다.

아래 emp테이블의 구조를 잠시 보자.

이렇게 desc로 컬럼의순서, null값의 허용, 컬럼의 데이터타입을 확인할수 있으며
empno같은 경우 null값을 허용하지 않기 때문에 INSERT로 값을 추가시킬때에는 꼭 적어주어야 한다는것을 알수있다.


아래의 INSERT문을 보고 잘못된점을 한번 찾아보도록 하자.
--- Question &---
1. insert into test1(deptno,dname,loc) values(50,'DESIGN'); 

2. insert into test1(deptno,dname,loc) values(50,'DESIGN','SEOUL',60);

3. insert into test1(deptno,dname,loccc) values(80,'DESIGN','SEOUL');

4. insert into test1(deptno,dname,loc) values('50','DESIGN','SEOUL'); 

5. insert into test1(deptno,dname,loc) values(60,'DESIGN',SEOUL); 

6. insert into test1(deptno,dname,loc) values(100,'DESIGN','SEOUL'); 

7. insert into test1(deptno, loc, dname) values(70,'DESIGN','SEOUL');  




--- & Answer ---
1. insert into test1(deptno,dname,loc) values(50,'DESIGN'); 
- > 기술된 컬럼의 수와 입력되는 값의 수가 일치하지 않는다.
values(50, 'DESIGN', null); 이라는 형태로 고칠수 있다. 
 
2. insert into test1(deptno,dname,loc) values(50,'DESIGN','SEOUL',60);
- > 기술된 컬럼의 수와 입력되는 값의 수가 일치하지 않는다.
 
3. insert into test1(deptno,dname,loccc) values(80,'DESIGN','SEOUL');
- > 컬럼명을 잘못 기술하였다. 

4. insert into test1(deptno,dname,loc) values('50','DESIGN','SEOUL'); 
- > deptno는 숫자형 테이터를 가지고 있는데 문자형으로 입력하였다.

5. insert into test1(deptno,dname,loc) values(60,'DESIGN',SEOUL); 
- > loc에 넣을 값을 ' '(홑따옴표)로 감싸 주지 않아 문자형으로 인식하지 못한다.
 
6. insert into test1(deptno,dname,loc) values(100,'DESIGN','SEOUL'); 
- > 얼핏보기에는 오류가 없어 보이지만 deptno의 테이터타입을 자세히 살펴보면
숫자형 2자리까지만 입력이 가능하다. 100은 3자리의 숫자이기 때문에 오류가 발생한다.


7. insert into test1(deptno, loc, dname) values(70,'DESIGN','SEOUL');  
- > loc에 DESIGN이 dname에 SEOUL이 들어가게 된다.
오류는 나지 않지만 후에 부서이름을 검색하는데 부서위치가 검색될수도 있으니 주의하자.

 
각 오류는 한글로 출력되기 때문에 알아보기 쉽다. 한번씩 적용해보자.
(필자는 영어로 나와서 알아보기 어렵다 ㅠㅠ) 
 


기본적인 INSERT문을 알아보았는데 값을 위 방법은 추가할 값을 하나하나 모두 적어주어야 한다.
하나하나 적을필요 없이 한번에 여러 값을 추가할수 있는 방법을 알아보자.

우선 서브쿼리문을 이용해보자.
CREATE문에서 서브쿼리문을 이용하여 생성시 여러값을 복사 시켜 생성하듯이
INSERT문도 CREATE문처럼 서브쿼리를 이용하여 여러값을 추가 시킬수 있다.

자 우선 dept테이블의 구조만 복사한 test2라는 테이블을 생성해보자.
구조만 복사할때에는 서브쿼리문 조건절을 항상 false값이 되도록 설정해주면 된다.


CREATE TABLE test2
AS select * from dept
where 1 = 0;





자 아무런 값은 복사하지 않고 dept테이블의 구조만 복사한 test2테이블에 dept의 모든값을 복사하여 추가해보자.


INSERT INTO test2
SELECT * FROM dept; 

4개의 row가 추가 되었다고 뜨며 
dept의 모든값이 복사된것을 확인할수 있다.
서브쿼리문에 WHERE절을 사용하면
자신이 원하는 값만 복사하는것도 가능하다.




서브쿼리로 값을 추가할때에 주의할점은 INSERT문에서 지정한 테이블과
서브쿼리문에서 지정한 테이블의 컬럼의 개수나 데이터 타입이 같아야 한다.
그럼 만약 아래 명령어를 실행하면 어떻게 될까?
INSERT INTO test2(LOC)
SELECT ename FROM emp;

자 INSERT문에서 지정한 테이블의 컬럼 갯수와 데이터 타입을 보자.
LOC라는 1개의 컬럼을 지정하였고 LOC는 문자형 타입이다.
서브쿼리문에서 지정한 테이블의 컬럼갯수 또한 ename라는 컬럼 하나를 지정하였고
ename의 데이터 타입도 문자형이다. 

그럼 위 조건(지정한 데이블의 컬럼의 개수, 데이터타입의 일치)
을 만족시키니 ename컬럼의 모든 값이 loc컬럼에 복사될것이다.

detptno와 dname는 따로 값을 추가 시키지 않아서 자동으로 null값이 입력된다.


다중테이블에 다중 로우 추가하기

이렇게 서브쿼리문을 이용하면 하나의 테이블에 여러값을 추가 시킬수 있다.
이번엔 INSERT ALL을 이용하여 여러 테이블에 여러값을 추가시키는 방법을 알아보자.

우선은 emp테이블을 이용하여 두개의 테이블을 만들어보자.
emp01 테이블에는 사원번호(empno), 사원명(ename), 월급(sal)컬럼의 구조만 복사하고
emp02 테이블에는 사원번호(empno), 사원명(ename), 입사날짜(hiredate)컬럼의 구조만 복사하여 생성하자.
(이제 테이블의 구조만 복사해서 생성하는것은 각자 할줄안다고 생각하여 따로 명령어는 적지 않겠다.)
자 생성된  emp01,emp02테이블에 부서번호가 20인 값들만 추가시켜보도록 하자.
 

1.INSERT ALL
2.INTO emp01 VALUES(empno, ename, sal)
3.INTO emp02 VALUES(empno, ename,
hiredate)

4.SELECT empno, ename, hiredate, sal
5.FROM emp 
6.
WHERE deptno = 20;  


자 한줄한줄 살펴보자.

1. 우선 INSERT ALL은 여러 테이블에 동시에 값을 입력하기 위한 명령어이다.
INSERT ALL을 먼저 기술하여 나는 다중테이블에 동시에 값을 입력하겠다고 명령내려준것이다.

2. "emp01테이블의 모든컬럼에 값(empno, ename, sal)을 추가하겠다." 라는 뜻이다.
(자 INTO emp01 테이블명 뒤에 컬럼이름이 없다. 컬럼이름을 넣지 않았을때에는 모든 컬럼을
추가시킨다는 뜻이라고 말했다.
뒤의 empno, ename, sal은 각각의 컬럼을 뜻하는것이다.)

3. 
"emp02테이블의 모든컬럼에 값(empno, ename, hiredate) 값을 추가하겠다." 라는 뜻이다.
(2번과 3번을 보면 한번에 두개의 테이블의 컬럼을 모두 지정해준것을 알수 있다. 
ALL을 빼고 각각 나누게 되면 일반적인  INSERT문과 다른점이 없다.)


4.자 여기서 값을 가져오는데 emp테이블의 empno, ename, hiredate, sal 컬럼을 가져온다고 기술하였다.
위 INSERT문에서 VALUES(값)을 컬럼으로 지정하였기때문에 컬럼을 가져오는것이다.
 

5. emp테이블에 값을 가지고 온다.

6. where절을 사용하여 deptno값이 20인 값들만 가져오도록 명령을 내렸다.

각 테이블을 확인해보자.

두개의 테이블에 동시에 여러값이 들어간것을 확인할수 있다.

조금 헷갈리는 부분이 있을듯하여 2,3번 문구를 한번더 설명하겠다.
INTO emp01 VALUES( 50, 'mir', 5000)
위 INTO문은 다들 이해할것이다. emp01테이블에 50번 사원의 mir의 월급은 5000이라고 값을 한줄 추가시키는것이다.

INTO emp01 VALUES( empno, ename, sal)

자 직역하면 emp01테이블의 모든 컬럼에 대한 값으로 empno, ename, sal컬럼을 넣는다는것이다.
값을 넣을때  ' '(홑따옴표)로 감싸주면 그 값을 문자형으로 인식하지만
숫자가 아닌 값을 ' '(홑따옴표)로 감싸주지 않으면 서버는 그 값을 컬럼으로 인식한다.

좀더 쉽게 하나의 컬럼에 다른 컬럼을 넣어보자.
INTO emp01(ename) VALUES(dname)
자 emp01테이블의 ename컬럼에 dname컬럼의 값을 넣는다는 뜻이다.
dname컬럼을 어디서 가져오는지는 서브쿼리문에서 기술해주면 된다.
INTO emp01(ename) VALUES(dname)
select dname from dept;

서브쿼리문에서 dname컬럼을 dept테이블에서 가져왔다.
자 그럼 직역하면 ename에 값을 dname컬럼값으로 넣는데
그 컬럼은 dept테이블에서 가져온다는 뜻이다.

위 예제를 보면
emp01테이블에서 empno, ename, sal컬럼을 값으로 추가하고 있고
emp02테이블에서는 empno, ename, hiredate컬럼을 값으로 추가하고 있다.
그래서 서브쿼리문을 보면 empno, ename, sal, hiredate컬럼을 emp테이블에서 가지고 오는데
조건을 걸어서 deptno가 20인 값들로만 가져오게 되는것이다.

서브쿼리문에서 가져온 값은 각각의 테이블에서 요구하는 컬럼에 대입되어
emp01테이블에서는 empno, ename, sal컬럼의 값을 가져가고
emp02 테이블에서는 empno, ename, hiredate컬럼의 값을 가져간다.



다중 테이블에 각각의 조건 추가하기
자 위 예제에서 다중테이블에 값을 입력시킬때에 INSERT ALL을 사용하여 한개 이상의 테이블을 호출하여 값을 추가시켰다.
위 예제를 보면 서브쿼리문에서 where절을 사용하여 deptno값이 20인것만 추가시켜주었다.
한마디로 공통된 조건의 값을 추가시켰다고 말할수 있다. 

이번엔 WHEN을 이용하여 각각 조건을 다르게 해서 값을 추가시키는 방법을 알아보자.

20번부서의 사람들중에 emp01에는 월급이 3000이상인 사람만 
emp02에는 이름에 A가 들어가는 사람만 추가시켜보도록 하자.

우선 다중테이블에 값을 입력시킨다고 명령을 내려주자.
INSERT ALL

각각의 조건을 WHEN절을 이용하여 적어준다.
emp01 = 월급이 3000이상인 사람 : WHEN  sal >= 3000 THEN
emp02 = 이름에 A가 들어가는 사람 : WHEN ename like %A% THEN

다시 한번 emp01과 emp02 테이블에 값을 추가시키는데 이전값과 구분하기 위해 EMPNO는 빼버리도록 하자.
INTO emp01(ename, sal) VALUES(ename, sal)
INTO emp02 (ename, hiredate) VALUES(ename, hiredate)


설정한 조건(WENN절)을 각각의 테이블에 맞게 넣어주면 된다.
WHEN  sal >= 3000 THEN
INTO emp01(ename, sal)
WHEN ename like %A% THEN
INTO emp02 (ename, hiredate)

그다음 서브쿼리문을 적어주면 된다.

INSERT ALL

WHEN  sal >= 3000 THEN
INTO emp01(ename, sal) VALUES(ename, sal)
WHEN ename like '%A%' THEN
INTO emp02(ename, hiredate) VALUES (ename, hiredate)
SELECT ename, hiredate, sal
FROM emp WHERE deptno = 20;  

그럼 각각의 테이블에 추가된 값을 확인해보자.


empno가 없는것이 각각의 조건을 주어 추가한 값이다.
emp01에는 3000이상의 월급을 가진 값들만 추가 되었고  emp02에는 이름에 A가 들어간사람만 추가된것을 확인할수 있다. 


INSERT문이 조금 복잡해 보일수도 있지만 위에서 말한 주의사항만 지키면 모두 성립된다.
가장 기본적인 주의사항 컬럼의 개수와 데이터타입의 일치는 서브쿼리문에서도 동일하게
적용되니 컬럼의 개수 일치, 데이터타입의 일치 이 두가지만이라도 꼭 기억해두자.


피벗 테이블(Pivot Table) 
자 마지막으로 INSERT문을 이용한 피벗 테이블(Pivot Table)에 대해 알아보자.
피벗 테이블이란 사용자가 원하는 일련의 값을 한눈에 쉽게 파악할수 있도록 요약을 해놓은 테이블이다.

예로 들자면 주간판매실적 테이블에 담긴 값들을 월간판매실적 테이블 혹은 년간 판매실적 테이블등으로 변경하여
주간판매실적 테이블을 이용하여 월간, 년간 판매실적을 한눈에 쉽게 알아볼수 있도록 고치는 것이다.
(여기에서는 INSERT문의 다중행 입력하기 기능을 설명하기 위해 피벗 테이블을 만들어 보는것이기 때문에
피벗 테이블에 더욱더 자세한 정의를 알고 싶으면 한번 검색해보는걸 추천한다.) 


자 그럼 예제를 하나 만들어 보자.
우선 월요일 부터 금요일까지의 매일매일 판매실적을 기록하는 테이블을 생성해보자.


CREATE TABLE sales(
sales_id NUMBER(5),
month_week NUMBER(4),
mon NUMBER(8, 2),
tue NUMBER(8, 2),
wed NUMBER(8, 2),
thu NUMBER(8, 2),
fri NUMBER(8, 2) );



그리고 난뒤 1월 한달동안의 실적을 한번 넣어보자.
INSERT INTO sales VALUES(00001, 11, 200, 100, 150, 200, 300);
INSERT INTO sales VALUES(00001, 12, 300, 300, 100, 250, 400);
INSERT INTO sales VALUES(00001, 13, 500, 100, 250, 500, 100);
INSERT INTO sales VALUES(00001, 14, 200, 500, 350, 200, 200); 
 

자 테이블을 보면 각 주마다 월요일부터 금요일까지의 매일매일 판매실적에 대해 나열되어있다.
이 테이블을 주간합계로 보는것은 간단하다. mon부터 fri까지 더해주면서 출력해주면 된다.

 
SELECT sales_id, month_week
mon+tue+wed+thu+fri week
from sales


주간합계를 week로 해딩변환해주고 난뒤 출력하면
1월 첫째주는 950 1월 둘째주는 1350 이렇게
주간판매실적을 쉽게 출력할수 있다.


이 sales테이블을 이용하여 하루하루 판매실적과 요일별 판매실적, 월간 판매실적등등 여러 피벗테이블을 만들어낼수 있다. 

셋다 어려울것은 없다.
월간 판매실적 같은경우는 week앞자리수가 같은것의 모든 실적을 더해주면 될것이고
매일매일 판매실적 같은경우는 mon~fri까지의 컬럼을 각각 나눠주면 된다.
요일별 판매실적은 요일별로 나눠 더해주면 된다.

그럼 매일매일 판매실적 피벗테이블을 한번 만들어보자.


CREATE TABLE sales_daily(

sales_id NUMBER(5),
month_week NUMBER(4),
sales NUMBER(8, 2));


sales_id와 month_week, 그리고 sales라는 컬럼을 가진 테이블을 생성해주었다.
이제 여기에 값을넣을때 mon부터 fri까지의 값을 각각 나누어 넣어야 한다. 어떻게 넣는지 한번 살펴보도록 하자.INSERT ALL
INTO sales_daily VALUES(sales_id, month_week, mon)
INTO sales_daily VALUES(sales_id, month_week, tue)
INTO sales_daily VALUES(sales_id, month_week, wed)
INTO sales_daily VALUES(sales_id, month_week, thu)
INTO sales_daily VALUES(sales_id, month_week, fri)
SELECT salse_id, month_week, mon, tue, wed, thu, fri
FROM sales;

여기서 보면 INSERT ALL을 사용하였다.
INSERT ALL은 다중테이블에 여러값을 넣을때 사용했었는데 이번엔 자세히 살펴보나 테이블명이 다 똑같다. 
다른점을 살펴보니 각 테이블마다 sales컬럼에 대입하는 컬럼이 바뀌고 있다.
첫번째 sales_daily테이블에서는 sales컬럼에 mon컬럼을 대입하고
두번째 sales_daily테이블에서는 sales컬럼에 tue컬럼을 대입하며
세번째 네번째 각각 sales컬럼에 대입하는 컬럼이 달라지고 있다.



추가한 값들을 한번 출력시켜보자

출력순서를 보면 mon값이 제일 위에 있고 
그다음 tue 다음은 wed값 순서대로 출력되는것을 볼수있다.

위 INSERT명령문에서 보면
처음에 salse_daily테이블의 salse컬럼에 mon컬럼을 모두
추가시키고 난뒤 두번째 명령을 보니 또다시 sales_daily테이블의
sales컬럼에 tue값을 추가 시켜라고 되어있다.
그렇게 순서대로 추가시키다 보니
mon~fri컬럼의 값이 각각 나눠지게 된것이다.

위와 같이 같은테이블에 INSERT ALL명령을 사용하여
여러개의 컬럼을 하나의 컬럼으로 합쳐 입력하는 방법을
다중행입력하기라고 한다.
(용어의 정의를 제대로 내렸는지는 확실치 않다;;
그냥 이런방법으로 값을 넣을수 있다는것만 알아두자
그냥 INSERT ALL을 응용하는 하나의 방법이라고  생각하는게
속도 편하고 머리도 편하다) 

테이블에 값을 추가하는 INSERT문과 그 응용방법에 대해 배워보았다.
실제로 프로그래머들은 INSERT를 데이터베이스와 프로그램의 연동할때에 많이 쓸것이며
데이터베이스관리자는 값을 이동 및 복사 할때 쓰일꺼라고 예상한다. 아무튼 기본적인 명령어이니 꼭 기억하자.



UPDATE(수정)
 

INSERT문으로 값을 넣었을때 혹 잘못된 값이나 수정해야될 값이 생길경우 UPDATE문을 사용하는데
UPDATE 테이블명
SET 컬럼명 = 변경할값
WHERE 조건
형식으로 사용되며 만약 조건절을 넣지 않을경우  SET으로 설정해둔 컬럼의 전체값이 변경되니 주의해야된다.

UPDATE문을 적용하기전 우선 dept테이블을 복사하여 test1테이블을 생성해보자.
이제 슬슬 테이블 생성 및 서브쿼리문을 이용하여 생성과 동시에 다른 테이블을 복사하는것은 모두 할수 있어야 된다.


만약 30번 부서 SALES가 시카고에서 서울로 부서위치(LOC)를 옮기게 되었을때 
우리는 데이터베이스 내의 부서위치를 수정시켜줘야 한다.


UPDATE test1   -  test1테이블을 수정하겠다고 명령을 내렸다.
SET LOC = 'SEOUL'  - LOC라는 컬럼의 값을 SEOUL로 바꾸겟다.
WHERE  deptno = 30;  - deptno가 30번인 값만 
 


test1테이블을 다시 살펴보면 deptno가 30인 행에서 loc의 값이 SEOUL로 바뀐것을 확인할수 있다.


UPDATE구문을 사용하여 다시한번 SEOUL을 CHICAGO로 수정해보도록 하자.

UPDATE구문에서 제일 중요한부분이 조건절이다. 만약 조건절을 적지 않았을때에는 어떻게 될까?
위 예제를 보았을때 조건절을 빼버리고 해석하면
tes1테이블의 loc라는 컬럼의 값을 SEOUL로 바꾸겠다.
라고 해석된다. 
어느 부분을 바꾸는게 아니라 loc컬럼의 값을 전체다 바꾸게 된다. 아래 예제를 보자.


LOC값이 모두 SEOUL로 바뀐것이 확인된다.
물론 전체의 값을 다 바꿔야 할때도 있을수도 있다. 
하지만 몇개의 값만 바꿔야 할때에 실수를 하여 이렇게 전체의 값을 변경하게 되면 정말 큰일난다.
(필자는 군에서 서버관리를 하였는데 한번은 소대장 이름을 바꾸다가 where절을 빼먹어서
 며칠동안 고생했다;;  그땐 필자도 책보고 겨우겨우 따라하는 정도여서 복구기능도 몰랐엇다. ㅠㅠ)
UPDATE문을 사용할때에는 항상 주의 하여 WHERE절을 한번더 확인해보도록 하자.

WHERE절과 연산자를 이용하면 복수의 행에대한 수정도 가능하다. 아래 예제를 보자.


UPDATE test1
SET loc = 'BOSTON'
WHERE deptno in ( 20, 30);


WHERE절에서 IN연산자를 이용하여 20과 30번의 부서를 모두 선택해주었다.
그 결과 20번 부서와 30번 부서의 LOC컬럼 값이 모두 BOSTON으로 변경 된것을 확인할수 있다.


UPDATE문도 서브쿼리문을 이용하는 방법이 있는데 다른테이블의 값을 가져와서 수정할수 있다.
자 아래예제에서 LOC값을 SEOUL로 모두 수정한뒤에 dept테이블내의 10번 부서의 loc값을 가져와 보았다.


UPDATE test1
SET loc =
(SELECT loc

                  FROM dept
                  WHERE deptno = 10 )

WHERE deptno = 10 ;

dept테이블내의 10번 부서의 loc값은
NEW YORK인데
그것을 test1테이블내의 10번 부서의
loc값에 대입시켜주었다.


이렇게 서브쿼리문을 이용하면 다른 테이블에 있는 값을 가져와서 수정할수도 있는데
서브쿼리문에서 꼭 하나의 행을 선택해주어야 한다. (복수의 행을 선택하면 안된다.)

왜냐 하면  UPDATE문을 이용할때 주의할점이 하나있는데
SET loc =  X 일때 X에는 복수의 값이 올수 없다.

무슨 뜻이냐면 loc컬럼의 값을 수정할려고 하는데
loc = 'SEOUL', 'NEW YORK'
이렇게 두개의 값으로 수정하라고 서버에 명령을 내리면 서버는 값을 순차적으로
대입시켜 loc의 값을 수정시키는 것이 아니라 둘중 하나를 loc컬럼 전체에 대입시킬려고 한다.  
하지만 둘중 어떤값을 대입시켜야 될지 모르기 때문에 오류가 나게 된다.

즉 UPDATE문은 INSERT문이나 CREATE문처럼 서브쿼리문을 이용하여
여러행을 한꺼번에 가져올수 없고 단 하나의 행만을 가져올수 있다.

자 다시한번 말하자면
"x를 y로 수정하여라" 라는 명령이 있을때 
x는 여러개의 값일수도 있다.( 1번 x도 y로 수정하고 2번 x도 y로 수정하고..)
하지만 y가 여러값이면 x를 1번 y이나 2번 y중 하나로 수정하라고 명령을 내리는것 처럼 된다.
그렇게 되면 서버는 어떤값으로 수정을 해야될지 모르기때문에 오류를 출력하게 된다.


마지막으로 update문을 이용하여 복수의 컬럼값을 한꺼번에 수정해보자.
방금전 까지 우리는 loc컬럼 하나만을 계속 수정해왔다. 이번엔 test1테이블의 전체적인 값을 수정해보자.
복수의 컬럼값을 수정하는 방법은 간단하다. 컬럼을 더 적어주면된다;;
아래와 같은 test1 테이블이 있다.

이 테이블을 deptno와 똑같은 값을 가지도록 수정해보자.

 


UPDATE test1
SET (deptno, dname, loc)
= (SELECT deptno, dname, loc
     FROM dept
     WHERE deptno=10)

WHERE deptno=10;

이렇게 복수의 컬럼을 변경할려면
SET뒤에 ( )를 넣어 복수의 컬럼을
지정해주면 된다.
WHERE절에서 deptno값을 10부터 40까지 넣어주면 dept테이블의 모든값과 똑같아 질것이다.
(수정해 놓고 생각해보니 deptno컬럼은 빼도 상관없다는걸 깨달았다.;;;)



DELETE(삭제)
 

값을 입력하고 수정하는 방법을 알아보았으니 이번에는 삭제하는 방법을 알아보자. DELETE문은
DELETE FROM 테이블명
WHERE 조건절

형식으로 사용하며 하나의 값을 삭제하는게 아니라 하나의 행(row)을 기준으로 삭제하게 된다.
그럼 test1의 10번 부서를 한번 삭제해보도록 하자.


DELETE FROM test1
WHERE deptno = 10;

결과를 보면 deptno가 10인 행(row)가
삭제된것을 확인할수 있다.




DELETE문도 WHERE절을 주의해야 하는데 만약 조건절을 적지 않았을 경우 테이블의 모든 값이 삭제 되어버린다.
그러니 꼭 WHERE절을 확인하도록 하자. 


MERGE(합병)
MERGE문은 구조가 같은 두개의 테이블을 하나의 테이블로 합칠때 사용하는 오라클에서만 제공하는 질의문이다.
두개의 테이블을 합친다고 하였는데 조금더 들어가면 두개의 테이블을 합친다는 개념보다 INSERT(추가)할때 만약 같은 값이 있으면 UPDATE를 하고 같은 값이 없으면 INSERT를 한다는 개념으로 생각하는게 좋다.
기본형식을 알아보자.

1. MERGE INTO (변경할 테이블명)                - 값을 변경할 테이블을 선언한다.
2.                USING (값을 가져올 테이블명)    - 어디에서 값을 가져올지 명시해준다.
3.                ON (조인 조건)                                - 조인조건을 명시해준다.
4. WHEN MATCHED THEN                            - 매치되는 값들이 있을때에
5.              UPDATE SET                                   - 업데이트(수정)한다.
6.              컬럼 1 = 값 1,                                     - 
컬럼1에 값1을
                 컬럼 2 = 값 2,
                           .
                           .
7. WHEN NOT MATCHED THEN                 - 매치 되는 값들이 없을때
8.              INSERT (컬럼1, 컬럼2...)

9.              VALUES (값1, 값2 ....)

자 위 기본구조를 보면 두개의 테이블을 값을 변경할 테이블과 값을 가져올 테이블을 정하고 난뒤
어떤값을 기준으로 조인하는지 선언하여 준다.
그리고 난뒤 매치되는 값이 있을때에는 수정을 하는 명령을 내려주고
매치되는 값이 없을때에는 추가하는 명령을 내려주는것이다.

예제를 통해서 한번씩 따라해보자.

우선 emp테이블을 복사한 test1테이블과 emp테이블에서 job이 MANAGER인 사람만 복사한 test2테이블을 만들어보자.



test을 값을 변경할 테이블 test2를 값을 가져올 테이블로 정할것인데
현재 모든값이 같기때문에 변화를 확인할수 없다.

그럼 우선 test2테이블을 살짝 변형해보자.
UPDATE test2 SET job = 'BOSS' ;

INSERT INTO test2 
VALUES (8000, 'MIR',  'KING', 8000, '2011/12/12', 5000, 3000, 60);

MANAGER을 BOSS로 수정해주었고 하나의 값을 더 넣어주었다.
그럼 MERGE문을 한번 적어보자.

우선 값을 변경할 테이블과 가져올 테이블을 나눠주자.
MERGE INTO test1 t1
               USING test2 t2
후에 좀더 쉽게 적을수 있도록 테이블의 별칭도 만들어 주었다. 
다음은 조인조건을 명시해주자.
ON( t1.empno = t2.empno)
만약 여기서 조인 조건을 job으로 적으면 test2와 tes1의 job을 비교 하기 때문에
매치되는 값이 하나도 생기지 않게 된다.
자 이제 update문구를 적어보자.
WHER MATCHED THEN  - test1의 empno와 test2의 empno의 값이 같으면
                    UPDATE SET  - 업데이트를 한다.
t1.ename = t2.ename,
t1. job = t2.job,
t1.mgr = t2.mgr,
             .
             .
test1의 empno와 test2의 empno의 값이 같을때 (조인조건을 t1.empno = t2.empno로 주었기때문에)
t1의 ename이 t2의 ename으로 변경되며 t1의 job이 t2의 job로 변경되는것이다.
물론 우리가 수정한 부분은 job뿐이기 때문에 그냥 job하나만 적어도 상관은 없다.
하지만 실제로 사용할때에는 어떤부분이 수정되었을지 모르기때문에 의심되는 값을 모두 적어주는게 좋다.

이번엔 INSERT문구를 적어보자.
WHER NOT MATCHED THEN - test1의 empno와 test2의 empno의 값이 다를때
INSERT VALUES (t2.empno, t2.ename, t2.job, t2.mgr, t2.hiredate, t2.sal, t2.comm, t2.deptno)
INSERT뒤에 아무런 컬럼을 안적으면 모든컬럼을 나타낸다고 말했던 것을 기억하자.
test1의 empno와 test2의 empno에서 다른값이 있을때 추가를 하게 된다.

자 그럼 위 명령어들을 종합하여 test1과 test2를 합병해보도록 하자.

test1의 테이블이 수정및 추가된것을 확인할수 있다.
MERGE문은 응용하기에 따라 다양하게 사용할수 있는데
UPDATE문이나 INSERT문 하나만 사용해도 되며 백업용으로 사용할수 있다.

한번 심심하면 MERGE문의 응용방법을 생각해보도록 하자.


이번 Chapter에서  DML의 가장기초인 INSERT(삽입), UPDATE(수정), DELETE(삭제)와 함께
오라클에서 제공하는 MERGE(합병)문을 살펴보았다.
MERGE는 자신의 일에 따라 사용을 할수도 안할수도 있지만 삽입, 수정, 삭제는 기본이기때문에 꼭 알아두기 바란다.


 

+ Recent posts