2020년 7월 20일 월요일

오라클, 데이터조작, DML(Data Manipulation Language), 단일, 복수행입력, INSERT, UPDATE, DELETE, MERGE

오라클, 데이터조작, DML(Data Manipulation Language), 단일, 복수행입력, INSERT, UPDATE, DELETE, MERGE

http://ojc.asia/bbs/board.php?bo_table=LecSQLnPlSql&wr_id=637

10. DML(Data Manipulation Language)

10.1 DML 개요

DML명령문은 스키마 오브젝트의 데이터를 접근하고 조작하는 명령문으로 다음과 같은 명령어들이 있다.

SELECT : 테이블의 데이터에 대해 접근 후 추출만 가능

INSERT : 테이블에 행을 삽입하기 위한 명령어

UPDATE : 테이블의 데이터를 수정하기 위한 명령어

DELETE : 테이블의 데이터를 삭제하기 위한 명령어

MERGE : 두 테이블의 데이터를 하나의 테이블로 병합하기 위한 명령어

10.2 INSERT 명령어

n 테이블에 데이터를 입력하기 위한 명령어

n 테이블에 데이터를 입력하기 위해서는 사용자 소유의 테이블이거나 테이블에 대해 INSERT 권한이 있어야 한다.

10.2.1 단일행 입력

[기본 형식]

INSERT INTO table_name [(column_name1, column_name2,,, )]

VALUES (value1, value2, ,,)

n 문자데이터 및 날짜 데이터는 VALUES 구에서 단일 따옴표(‘)로 싸야 한다.

n 테이블의 모든 칼럼에 대해 데이터를 삽입하는 경우에는 INTO 테이블이름 다음에 칼럼을 기술하지 않아도 되고 VALUES절에서 테이블에 정의된 칼럼의 순서대로 값을 기술하면 된다. (추후 테이블에 칼럼이 추가 된다면 오류 발생한다)

n 테이블의 일부 칼럼에만 값을 입력하는 경우에는 INTO 테이블이름 다음에 반드시 칼럼을 기술해야 한다.

n 칼럼에 NULL을 입력하는 방법은, INSERT INTO 테이블명 다음에 칼럼명 나열 시 NULL을 입력 할 칼럼을 기술하지 않으면 묵시적으로 NULL이 입력되고 명시적으로 VALUES절에서 NULL 또는 ‘’을 입력해 주면 된다.

n VALUES 절에는 현재 사용자 계정을 나타내는 USER, 칼럼의 기본값을 나타내는 DEFAULT와 SYSDATE와 같은 함수 사용 가능 하다.

n 날짜 데이터는 날짜데이터로 변환해서 입력하거나 문자열을 입력한다면 해당 시스템의 NLS_DATE_FORMAT에 맞추어 입력해야 한다.

SQL> drop table t1;

테이블이 삭제되었습니다.

SQL> create table t1 (

a number,

b varchar2(10),

c date not null,

constraint pk_t1 primary key(a),

constraint ck_t1_b check (b in ('oracle','java')));

테이블이 생성되었습니다.

SQL> insert into t1 values (1, 'oracle', sysdate);

1 개의 행이 만들어졌습니다.

--이미 a칼럼에 1이 있다.(a 칼럼은 PK칼럼으로 NOT NULL 이면서 Uniquey Key 제약조건을 가지면 별도 인덱스가 만들어 진다)

SQL> insert into t1 values (1, 'oracle', sysdate);

insert into t1 values (1, 'oracle', sysdate)

*

1행에 오류:

ORA-00001: 무결성 제약 조건(SCOTT.PK_T1)에 위배됩니다

SQL> insert into t1 values (2, 'java', sysdate);

1 개의 행이 만들어졌습니다.

--a 칼럼은 PK이므로 NOT NULL 칼럼이다.

SQL> insert into t1 values (NULL, 'java', sysdate);

insert into t1 values (NULL, 'java', sysdate)

*

1행에 오류:

ORA-01400: NULL을 ("SCOTT"."T1"."A") 안에 삽입할 수 없습니다

--c 칼럼은 DATE형으로 NOT NULL 제약조건이 정의되어 있다.

SQL> insert into t1 values (30, 'java', NULL);

insert into t1 values (30, 'java', NULL)

*

1행에 오류:

ORA-01400: NULL을 ("SCOTT"."T1"."C") 안에 삽입할 수 없습니다

--b 칼럼은 CHECK 제약조건으로 ‘oracle’, ‘java’ 값만 입력되도록 되어 있으므로 오류

SQL> insert into t1 values (30, 'c#', sysdate);

insert into t1 values (30, 'c#', sysdate)

*

1행에 오류:

ORA-02290: 체크 제약조건(SCOTT.CK_T1_B)이 위배되었습니다

--c 칼럼은 NOT NULL 칼럼이므로 오류

SQL> insert into t1(a, b) values (30, 'oracle');

insert into t1(a, b) values (30, 'oracle')

*

1행에 오류:

ORA-01400: NULL을 ("SCOTT"."T1"."C") 안에 삽입할 수 없습니다

-- c 칼럼이 DATE형이지만 NLS_DATE_FORMAT에 맞게 문자열을 입력하면 잘 입력된다.

SQL> insert into t1(a, b, c) values (30, 'oracle','14/10/01');

1 개의 행이 만들어졌습니다.

SQL> column parameter format a20

SQL> column value format a20

SQL> select * from nls_session_parameters

where parameter = 'NLS_DATE_FORMAT';

PARAMETER VALUE

-------------------- --------------------

NLS_DATE_FORMAT RR/MM/DD

--c 칼럼은 NOT NULL 칼럼이다.

SQL> insert into t1(a, b, c) values (40, 'oracle', NULL);

insert into t1(a, b, c) values (40, 'oracle', NULL)

*

1행에 오류:

ORA-01400: NULL을 ("SCOTT"."T1"."C") 안에 삽입할 수 없습니다

-- b 칼럼은 NULL을 허용하는 칼럼이다.(b 칼럼에 묵시적으로 NULL을 입력)

SQL> insert into t1(a, c) values (40, sysdate);

1 개의 행이 만들어졌습니다.

-- 이번에는 b 칼럼에 기본값을 설정하자.

SQL> alter table t1 modify b default 'oracle';

테이블이 변경되었습니다.

-- b 칼럼만 insert 칼럼 리스트에서 제외하는 경우에는 b 칼럼은 기본값으로 설정된다.

SQL> insert into t1(a, c) values (50, sysdate);

1 개의 행이 만들어졌습니다.

-- 명시적으로 NULL 이라고 입력을 하면 b 칼럼은 기본값으로 설정되지 않는다.

SQL> insert into t1(a, b, c) values (60, NULL, sysdate);

1 개의 행이 만들어졌습니다.

SQL> select * from t1;

A B C

---------- ---------- --------

1 oracle 14/09/11

2 java 14/09/11

30 oracle 14/10/01

40 14/09/11

50 oracle 14/09/11

60 14/09/11

-- b 칼럼의 길이를 늘이고, CHECK 제약조건을 삭제하자.

SQL> alter table t1 modify b varchar2(50);

테이블이 변경되었습니다.

SQL> alter table t1 drop constraint ck_t1_b;

테이블이 변경되었습니다.

-- 현재 접속한 사용자명을 나타내는 USER 키워드 사용가능

SQL> insert into t1 (a, b, c) values (70, USER, sysdate);

1 개의 행이 만들어졌습니다.

--칼럼의 기본값을 나타내는 DEFAULT 키워드 사용가능, b 칼럼에 설정한 기본값이 입력된다.

SQL> insert into t1 (a, b, c) values (80, DEFAULT, sysdate);

1 개의 행이 만들어졌습니다.

SQL> select * from t1;

A B C

---------- -------------------------------------------------- --------

1 oracle 14/09/11

2 java 14/09/11

30 oracle 14/10/01

40 14/09/11

50 oracle 14/09/11

60 14/09/11

70 SCOTT 14/09/11

80 oracle 14/09/11

SQL> commit;

10.2.2 복수행 입력(Multi Row Insert)

여러행을 한번에 입력하기 위한 방법은 INSERT … SELECT… 와 같이 서브쿼리를 이용하는 방법과 오라클9i 이후 사용가능한 INSERT ALL[FIRST] 등을 이용하는 방법이 있다.

서브쿼리를 이용한 다중행 입력

[기본 형식]

INSERT INTO table_name [(column_name1, column_name2,,, )]

Sub Query

n 서브쿼리는 SELECT문이며 서브쿼리의 결과(자신이나 다른 테이블의 SELECT 결과)로 넘어오는 레코드를 한번에 INSERT 한다.

n INSERT INTO 테이블명 다음에 칼럼을 기술하는 경우에는 해당 칼럼만 데이터를 INSERT 하겠다는 의미로 서브쿼리에서 SELECT 되는 칼럼 개수와 타입이 일치해야 한다. 칼럼을 기술 안하는 것은 테이블의 모든 칼럼에 대해 INSERT 하겠다는 의미이다.

n 서브쿼리의 결과로 SELECT되는 ROW가 없다면 테이블에 한건도 INSERT하지 않는다.

--EMP테이블의 구조만 복사하여 EMP_TEST 테이블을 생성

SQL> create table emp_test (sabun, name, salary, deptno)

as

select empno, ename, sal, deptno from emp

where 1 = 2;

테이블이 생성되었습니다.

SQL> insert into emp_test (sabun, name, salary, deptno)

select empno, ename, sal, deptno from emp

where deptno = 10;

3 개의 행이 만들어졌습니다.

SQL> select * from emp_test;

SABUN NAME SALARY DEPTNO

---------- ---------- ---------- ----------

7782 CLARK 2450 10

7839 KING 5000 10

7934 MILLER 1300 10

--아래는 스칼라 서브쿼리(Scarlar SubQuery)를 이용하는 방법이다.

SQL> insert into emp_test (sabun, name) values (

(select empno from emp where rownum < 2),

(select ename from emp where rownum < 2));

1 개의 행이 만들어졌습니다.

SQL> select * from emp_test;

SABUN NAME SALARY DEPTNO

---------- ---------- ---------- ----------

7782 CLARK 2450 10

7839 KING 5000 10

7934 MILLER 1300 10

7369 SMITH

INSERT ALL/FIRST을 이용한 다중행 입력

[기본 형식]

INSERT ALL | FIRST

INTO [table] VALUES [(Column1, Column2,,,)]

INTO [table] VALUES [(Column1, Column2,,,)]

……

Sub Query

n Oracle 9i 이후에 사용 가능한 명령으로 하나의 테이블에 여러 데이터를 입력하거나, 여러 테이블에 하나의 INSERT 명령으로 동시에 데이터를 입력할 수 있다.

1. Unconditional Insert ALL : 서브쿼리의 결과를 조건없이 모든 테이블에 입력

create table emp_job_info as select ename, job from emp where 1 > 100;

create table emp_sal_info as select ename, sal from emp where 1 > 100;

select count(*) from emp

COUNT(*)

----------

14

-- emp 테이블의 모든 데이터를 조건없이 emp_job_info, emp_sal_info 에 입력

insert all

into emp_job_info values (ename, job)

into emp_sal_info values (ename, sal)

select ename, sal, job from emp

28개 행 이(가) 삽입되었습니다.

select * from emp_job_info

ENAME JOB

---------- ---------

SMITH CLERK

ALLEN SALESMAN

WARD SALESMAN

select * from emp_sal_info

ENAME JOB

---------- ---------

SMITH 1000

ALLEN 9000

WARD 1250

2. Conditional Insert ALL : 모든 데이터를 같거나 다른 테이블에 다중 INSERT 가 가능하지만 특정 조건에 따라 INSERT. 동시에 여러 조건에 만족한다면 모든 INSERT문이 실행된다.

Delete from emp_job_info;

Delete from emp_sal_info;

-- emp 테이블에서 모든 행을 선택하여 emp_job_info에는 10번부서 데이터를, emp_sal_info에는 20부서의 데이터를 입력하시오.

insert all

when deptno = 10 then

into emp_job_info values (ename, job)

when deptno = 20 then

into emp_sal_info values (ename, sal)

select ename, sal, job, deptno from emp

8개 행 이(가) 삽입되었습니다.

select * from emp_sal_info

ENAME JOB

---------- ---------

SMITH 1000

JONES 2975

SCOTT 1000

ADAMS 1100

FORD 3000

select * from emp_job_info

ENAME JOB

---------- ---------

CLARK MANAGER

KING PRESIDENT

MILLER CLERK

10번 부서는 emp_job_info에 20번 부서는 emp_sal_info에 삽입하고, 부서관계없이 급여가 2500 보다 큰 직원은 emp_sal_info에 입력하라.

Delete from emp_job_info;

Delete from emp_sal_info;

insert all

when deptno = 10 then

into emp_job_info values (ename, job)

when deptno = 20 then

into emp_sal_info values (ename, sal)

when sal > 2500 then --위 두조건을 만족했던 행들도 sal > 2500 이라면 아래 into절 실행된다.

into emp_sal_info values (ename, sal)

select ename, sal, job, deptno from emp;

15 rows created.

select * from emp_job_info;

ENAME JOB

---------- ---------

CLARK MANAGER

KING PRESIDENT

MILLER CLERK

3 rows selected.

아래에서 SCOTT, JONES, FORD는 두번 INSERT 되었다.

select * from emp_sal_info;

ENAME SAL

---------- ----------

SMITH 800

JONES 2975

SCOTT 3000

ADAMS 1100

FORD 3000

JONES 2975

BLAKE 2850

SCOTT 3000

KING 5000

FORD 3000

3. Conditional Insert First : 서브쿼리의 데이터를 WHEN 조건절에서 지정한 조건을 만족하는 첫번째 테이블에만 INSERT, 다음 레코드도 이와 같은 방식으로 INSERT 한다.

delete from emp_job_info;

delete from emp_sal_info;

-- emp 테이블에서 모든 데이터를 선택하여 emp_job_info에는 job이 ‘MANAGER’인 데이터를, emp_sal_info 에는 sal값이 2000보다 큰 데이터를 입력하시오. 단 두조건을 모두 만족하는 경우라면 emp_job_info에만 입력하고 job이 ‘MANAGER’도 아니도 sal값이 2000보다 작거나 같은 경우에는 emp_sal_info 에 입력 하시오.

insert first

when job = 'MANAGER' then

into emp_job_info values (ename, job)

when sal > 2000 then

into emp_sal_info values (ename, sal)

else

into emp_sal_info values (ename, sal)

select ename, sal, job, deptno from emp

14개 행 이(가) 삽입되었습니다.

select * from emp_job_info

ENAME JOB

---------- ---------

JONES MANAGER ß ‘MANAGER’이면서 sal 칼럼이 2000보다 크지만 emp_job_info만 입력

BLAKE MANAGER

CLARK MANAGER ß ‘MANAGER’이면서 sal 칼럼이 2000보다 크지만 emp_job_info만 입력

select * from emp_sal_info

ENAME JOB

---------- ---------

ALLEN 9000

KING 5000

FORD 3000

……

ADAMS 1100

JAMES 950

MILLER 1300

10.3 UPDATE 명령어

n 테이블의 데이터를 변경하기 위한 명령어

n 자신 Schema에서 만든 테이블 이거나 테이블에 대한 UPDATE 권한이 있어야 한다.

n WHERE 조건을 생략하면 테이블의 모든 레코드가 변경되므로 조심해야 한다.

n WHERE 조건은 칼럼명, 표현식, 상수, 서브쿼리, 비교연산자 등이 올 수 있다.

[기본 형식]

UPDATE [table_name | subquery]

SET column = value[,column = value]

[WHERE 조건]

1. EMP 테이블에서 이름이 ‘SMITH’인 사원의 급여를 1000으로 변경 하시오.

update emp

set sal = 1000

where ename = 'SMITH'

2. 서브 쿼리를 이용한 UPDATE : EMP 테이블에서 이름이 ‘SMITH’인 사원의 급여를 이름이 ‘FORD’인 사원의 급여로 수정 하시오.

update emp

set sal = (select sal from emp where ename = 'FORD' )

where ename = 'SMITH'

10.4 DELETE 명령어

n 테이블 데이터를 삭제하기 위한 명령어

n 자신 Schema에서 만든 테이블이거나 테이블에 대한 DELETE 권한이 있어야 한다.

n WHERE 조건을 생략하면 테이블의 모든 레코드가 삭제되므로 조심해야 한다.

n WHERE 조건은 칼럼명, 표현식, 상수, 서브쿼리, 비교 연산자 등이 올 수 있다.

[기본 형식]

DELETE [FROM] table_name

[WHERE 조건]

1. EMP 테이블에서 이름이 ‘SMITH’인 사원의 데이터를 삭제 하시오.

Delete From emp

where ename = 'SMITH'

2. 서브 쿼리를 이용한 DELETE : EMP 테이블에서 부서명이 ‘SALES’인 데이터를 삭제하시오. (부서명 칼럼은 DEPT 테이블에 존재한다.)

delete from emp

where deptno = (

select deptno from dept

where dname = 'SALES'

)

10.5 MERGE 명령어

n 테이블 데이터를 병합하기 위한 명령어

n 병합되는 테이블에 데이터가 있는 경우에는 UPDATE, 없는 경우에 INSERT등의 로직을 구현할 수 있다.

[기본 형식]

MERGE INTO table_name alias

USING [table_name | view | subquery] alias

ON (조인 조건)

WHEN MATCHED THEN

UPDATE SET col1 = val1 [,col2 = val2…]

WHEN NOT MATCHED THEN

INSERT (column_list) VALUES (value_list)

n MERGE INTO 구 : 데이터가 update 되거나 insert될 테이블명(병합되는 테이블명)

n USING 구 : 머지되는 대상 table의 data와 비교한 후 update 또는 insert할 때 사용할 데이터 원본

n ON 구 : update나 insert를 하게 될때의 조건, 조건을 만족하는 레코드가 있으면 WHEN MATCHED 이하를 실행하고 없으면 WHEN NOT MATCHED 이하를 실행한다.

n WHEN MATCHED : ON 조건이 TRUE인 경우 수행할 내용

n WHEN NOT MATCHED : ON 조건이 false인 경우 수행할 내용

CREATE TABLE emp_20

AS SELECT * FROM emp WHERE deptno = 20;

select * from emp_20

EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO

---------- ---------- --------- ---------- -------- ----------------------------------- ---------- ----------

7369 SMITH CLERK 7902 80/12/17 1000 20

7566 JONES MANAGER 7839 81/04/02 2975 20

7788 SCOTT ANALYST 7566 87/07/13 1000 20

7876 ADAMS CLERK 7788 87/07/13 1100 20

7902 FORD ANALYST 7566 81/12/03 3000 20

-- emp 테이블의 데이터를 원본으로 emp_20에 데이터가 이미 있으면 sal 값을 10% 증가,

없으면 insert

MERGE INTO emp_20 e20

USING emp e

ON(e20.empno = e.empno)

WHEN MATCHED THEN

UPDATE SET e20.sal = e.sal*1.1

WHEN NOT MATCHED THEN

INSERT (empno, ename, sal) VALUES (e.empno, e.ename, e.sal);

select * from emp_20

댓글 없음:

댓글 쓰기

(C#교육동영상)C# ADO.NET 실습 ODP.NET/ODAC 설치 오라클 함수 호출 실습, C#학원, WPF학원, 닷넷학원, 자바학원

  (C#교육동영상)C# ADO.NET 실습  ODP.NET/ODAC 설치  오라클 함수 호출 실습, C#학원, WPF학원, 닷넷학원, 자바학원 https://www.youtube.com/watch?v=qIPU85yAlzc&list=PLxU-i...