학원수업_Oracle

201007 Oracle DML

logloglog 2020. 10. 7. 13:29

 DML (SELECT, INSERT, UPDATE, DELETE) 

 

1. INSERT

테이블에 자료를 삽입하는 명령

 

(사용형식)

INSERT INTO 테이블명[(컬럼명,컬럼명,...)]
VALUES(값,값,...);

 

INSERT는 INTO와 함께쓴다.

 

- 컬럼명이 생략되면 (테이블명만 기술하는 경우) 테이블에 정의된 모든 컬럼에 값을 VALUES 절에서 기술해야함 (순서도 일치)

- (컬럼명,컬럼명,...)은 컬럼 일부만 값을 배정할 수 있다. 단 NOT NULL인 컬럼은 절대 생략 불가능(기본키,외래키도 빠뜨리면 안된다) (지정되지않은 컬럼값은 null로 들어감)

 

*테이블만든순서대로 초기데이터를 넣어줘야함..

즉 어제만든 테이블중 CUST테이블부터 INSERT해줄것

 

 

EX ) CUSTS테이블에 다음 자료를 입력하세요

 

회원번호/이름/전화번호/주소

A001/홍길동/010-1234-5678/대전시 중구 대흥동 500

B001/강감찬/042-222-8202/대전시 중구 소제동 500

C001/이성계/010-9876-5432/서울시 성북구 장위2동 1000

 

오라클의 문자열은 자바의 문자열과 달리 ""가 아니고 '  '
오라클에서 ""은 딱 두군데만 쓰임
한글은 글자 하나가 3BYTE 영문숫자기호는 한글자가 BYTE

010-1234-5678은 13BYTE

서울시 중구 장위2동 1000 < 공백까지 세야함

 

SELECT절은 크게 SELECT(열)(모든열은 *) FROM (+테이블명) 가 필수! 만약 조건이있다면 WHERE(행) 까지가 필수절

만약 컬럼의 원래순서와 다르게 INSERT INTO CUSTS(CUST_ID, ADDR, CUST_NAME, TEL_NUM) 이렇게쓴다면?

상관없다.

그 후에 (값,값,,쓸때 위에 쓴 순서대로 입력해주면 됨.

 

INSERT INTO CUSTS
VALUES('A001','홍길동','010-1234-5678','대전시 중구 대흥동 500');

INSERT INTO CUSTS
VALUES('B001','강감찬','042-222-8202','대전시 중구 소제동 500');

INSERT INTO CUSTS
VALUES('C001','이성계','010-9876-5432','서울시 성북구 장위2동 1000');

SELECT * FROM CUSTS;

 

 

 

근데 만약 전화가 없는 사람이있다?

INSERT INTO CUSTS
VALUES('D001','고라니','서울시 성북구 장위2동 1000');

이렇게 하면 안됨.

3번째가 TEL_NUM으로 들어가야하는데 .. 오류남

오류 보고 -
SQL 오류: ORA-00947: not enough values

전화번호에 들어가야할 값 ''을 써줌 (WHITE SPACE)(공간안주고 외따옴표를 연속으로 친것)

 

INSERT INTO CUSTS
VALUES('D001','고라니','','서울시 성북구 장위2동 1000');

 

 

다른방법은 입력할 컬럼만 지정해주는것

INSERT INTO CUSTS(CUST_ID,CUST_NAME)
VALUES('E001','김통통');

TEL_NUM과  ADDR 가 NULLABLE이기 때문에 가능함

 

 

이제 GOODS테이블

NUMBER(7)만했는데 7,0? 0은 소숫점자릿수를 뜻함. 소숫점뒤 자릿수가 없다는 말.

 

EX) 상품테이블에 다음 자료를 입력하시오

상품번호 상품명 가격
P01 마우스 12000
P10 지우개  
P20 모니터 250000

 

오답:

INSERT INTO GOODS
VALUES('P01','지우개',NULL);

오류 보고 -
ORA-00001: unique constraint (CAS.PK_GOODS) violated

 

>P10인데 마우스와 같은 상품번호 P01을 해서!!!

 

INSERT INTO GOODS
VALUES('P10','지우개','');

이렇게 해도 삽입이 됨. 근데 ''은 NULL인데 가격타입은 NUMBER임. 문자열이 숫자로 들어간다?

자바에선 절대안된다. 근데 '자동형변환'이 된거임

 

자바는 7+'5' = 75
오라클은 12가 됨 ( 자동형변환 )

 

결과 :

INSERT INTO GOODS
VALUES('P01','마우스',12000);

INSERT INTO GOODS
VALUES('P10','지우개','');

INSERT INTO GOODS
VALUES('P20','모니터',250000);

PRICE의 DEFAULT VALUE는 0인데 NULL이 들어감. 사용자가 NULL을 지정했기때문임. DEFAULT VALUE는 사용자가 아예 값을 지정하지않았을때의 값이고, NULL도 데이터임.

그럼 DEFAULT 값을 어떻게 적용하냐?

INSERT INTO GOODS(GOOD_ID,GOOD_NAME)
VALUES('P31','마우스패드');

사용자가 아예 값을 입력하지않으니까 디폴트값인 0이 들어감

 

아까처럼 NULL값이 들어가면 나중에 수량곱하기 가격을 해야하는데

10*0이 되어야하는데 10*NULL 이되니까 문제가 될수있음

 


홍길동이 오늘 지우개를 열개 마우스를 2개샀다 > ORDER_GOODS에 저장해야함

근데 이사람이 로그인했을때

ORDERS안에 장바구니가 만들어지고,

바구니 번호가 생성되어야 물건을 장바구니에 담을수있음 > 이건 어플리케이션에서 해주는것

 

ORDERS의 ORDER_NUM을 보면, 원래는 년월일포함해서 만들어야하지만 우리는 NUM(4) 즉 9999명까지 수용할수있게만들었음

 

EX) 홍길동 고객이 오늘 지우개 10개, 모니터2개를 구매했을때 ORDERS테이블과 주문상품(ORDER_GOODS)테이블에 자료를 입력하시오.

 

우선 ORDERS GOOD에 보면 장바구니 넘버가 필요하므로 ORDERS에 먼저가야함

 

**지금은 ORDER_NUM을 수동으로 입력하지만 나중에는 서브쿼리 이용해서 제일 마지막값(제일큰값)+1이 되게 해서 자동으로 번호부여될수있게할거임.. CUST_ID도 

SELECT CUST_ID FROM CUSTS WHERE CUST_NAME='홍길동';

이렇게 할거임

 

INSERT INTO ORDERS(ORDER_NUM,CUST_ID)
    VALUES(1,'A001');

DATE는 입력안했더니 SYSDATE 나옴

 

 

이제 홍길동이 지우개10개 모니터 2개 산거 기록해야함

INSERT INTO ORDER_GOODS
    VALUES(1,'P10',10);

모니터 산것도

INSERT INTO ORDER_GOODS
    VALUES(1,'P20',2);

 

그럼 홍길동이 지불해야할 금액은?

 

ORDER_GOODS에는 가격이 없으므로 절대안됨

 

그전에 지우개 가격을 NULL원으로 했으니까

UPDATE GOODS
    SET PRICE=500
    WHERE GOOD_ID='P10';

이제 홍길동이 지불해야할 금액을 계산해보자

SELECT B.GOOD_NAME AS "상품명",
        C.QTY AS "구매수량",
        B.PRICE AS "단가",
        C.QTY*B.PRICE AS "지불금액"
FROM GOODS B, ORDER_GOODS C
WHERE C.ORDER_NUM=1
AND B.GOOD_ID=C.GOOD_ID;

 

합산하려면

SELECT SUM(C.QTY*B.PRICE) AS "지불금액"
FROM GOODS B, ORDER_GOODS C
WHERE C.ORDER_NUM=1
AND B.GOOD_ID=C.GOOD_ID;

 

컬럼의 별칭을 쓸때 쌍따옴표를 쓴다.

 

 

 

 

 UPDATE문 

이미 저장된 자료는 INSERT 쓸수없음. 중복된 자료... ( 물론 동명이인인 경우는 회원번호가 다르면 됨)

근데 UPDATE와 DELETE는 해당자료가 이미 있을때 사용할수있는것.

없는건 INSERT 이미 존재하고있는 자료에 대해서 수정하거나 지울때 UPDATE DELETE

 

테이블에 이미 저장되어있는 자료의 일정부분을 수정할 때

 

*사용형식

UPDATE 테이블명 
SET 컬럼명=값[,]      // (컬럼명,컬럼명,...)=(값,값,...) 이런식으로 쓰기도,,(반드시 짝 같아야함)
    [컬럼명=값,]
        :
    [컬럼명=값]
[WHERE 조건];    // WHERE는 행이므로 WHERE 없으면 조건에 맞는거 뽑아서 변경하는것 대신 그테이블의 모든 컬럼변경

UPDATE 는 SET와 함께임

 

 

EX ) 상품테이블(GOODS)에서 지우개의 판매단가를 1200으로 변경하시오

UPDATE GOODS
SET PRICE=1200
WHERE GOOD_ID='P10';

COMMMIT;

하드디스크에 저장됨

 

근데 만약 실수로

UPDATE GOODS
SET PRICE=1200

WHERE절을 안썼더니 모두 1200원으로 바꼈다.

이럴때에는 다시 ROLLBACK 해줌

ROLLBACK;

다시 돌아왔따.

 

 DELETE문 

테이블에 존재하는 자료를 삭제할 때 사용하는 명령

 

*사용형식

DELETE 테이블명
[WHERE 조건];    //WHERE절이 생략되면 테이블의 모든 자료가 삭제된다.

EX) CUSTS테이블의 고라니자료를 삭제하자

DELETE CUSTS
WHERE CUST_ID='D001';

근데 만약 홍길동자료를 삭제하려고 하면, 구매기록이 있기때문에 삭제가 안된다.

 

 

 

 

EX) 고객테이블(CUSTS), 상품테이블(GOODS), 주문(ORDERS), 주문상품(ORDER_GOODS) 테이블을 삭제하시오

DROP TABLE ORDER_GOODS;
DROP TABLE ORDERS;
DROP TABLE GOODS;
DROP TABLE CUSTS;

 

 

 

 

 

 

 

 SQL의 데이터 타입 

 

1. 문자데이터 타입 (CHAR, VARCHAR, VARCHAR2, CLOB, LONG, NVARCHAR, NVARCHAR2, NCLOB (N이 붙으면

UTF8이나 UTF16방식으로,, 표준어코드로 데이터를 저장하는 방식임))

 

 

(1) CHAR

 

- 고정길이 문자열을 저장하기 위한 데이터 타입

   사용자가 정의한 그 크기만큼 입력을 안하더라도 오른쪽에 빈공간이 생김. 즉 왼쪽에서 오른쪽방향으로 채워짐

- 사용자가 정의한 데이터가 기억공간보다 작으면 기억장소의 오른쪽에 빈공백이 채워짐(패딩)

- 사용자가 정의한 데이터가 기억공간보다 크면 저장 오류

  10글자로 정했는데 15자 입력하면 잘라서 저장? NO 아예 오류임

- 최대 2000BYTE까지 사용가능 (즉 영문자 기준 2000글자. 한글은 3으로 나누면 666글자)

- 한글 한글자는 3BYTE로 처리됨

 

*사용형식

컬럼명 CHAR(크기 [BYTE|CHAR])
    //'BYTE|CHAR'가 생략되면 BYTE로 간주(디폴트가 BYTE)
    //'크기 CHAR'로 표현되더라도 2000BYTE를 초과할 수 없음

 

 **BIT ? BYTE ? 
컴퓨터에서 사용되는 가장작은 표현단위가 BIT
실제 의미있는 정보가 되어 저장하는 최소단위가 (주기억장치에 번지가 부여되는 최소단위)가 BYTE

 

EX

CREATE TABLE TEMP01(
    COL1 CHAR(10),
    COL2 CHAR(10 BYTE),
    COL3 CHAR(10 CHAR)
);
INSERT INTO TEMP01(COL1,COL2,COL3)
    VALUES('ABCDEFG','12345','대한민국');

COL1에 10BYTE 2에 10BYTE 3에 18BYTE (대한민국이 3*4=12바이트 차지. 10CHAR니까 나머지 6CHAR남아있으니 12+6)

 

SELECT LENGTHB(COL1),LENGTHB(COL2),LENGTHB(COL3)
FROM TEMP01;

LENGHTH(길이)B(바이트)를 구하는 함수

즉 고정길이는 글자를 쓰건말건 전체길이는 똑같다.

 

데이터를 한글로 안쓰면 살짝 달라짐

INSERT INTO TEMP01(COL1,COL2,COL3)
    VALUES('ABCDEFG','12345','IL POST');

 

( 왜 18이 되지????잘모르것음...)

(2) VARCHAR2

 

- 가변길이 문자열을 저장

  사용자가 입력한 만큼만 쓰고 나머지는 OS에 반환해서 다른곳에 쓸수있도록한다.

- 사용자가 입력한 길이만큼 사용

- 최대 4000BYTE까지 사용가능

- 가장 많이 사용되는 데이터타입

- 오라클에서만 사용가능

 

*사용형식

컬럼명 VARCHAR2(크기 [BYTE|CHAR])   //생략되면 BYTE로 간주된다.

 

EX

 

TEMP02 테이블을 만든 후

CREATE TABLE TEMP02(
    COL1 VARCHAR2(100),
    COL2 VARCHAR2(100 BYTE),
    COL3 VARCHAR2 (100 CHAR)
);
INSERT INTO TEMP02(COL1,COL2,COL3)
    VALUES('JOHN RUSSEL','1234567890','대전시 중구 대흥동 500번지');

빈공간이 하나도 없이 저장되었다.

나머지는 빈공간으로 채워넣는 CHAR와 달리 VARCHAR2는 쓸것만 쓰고 나머지는 반환하였다.

 

TEMP02의 길이를 나타내보면

SELECT LENGTHB(COL1),LENGTHB(COL2),LENGTHB(COL3)
FROM TEMP02;

숫자나 공백은 1BYTE씩이다.

 

 

 

(3) VARCHAR

 

- VARCHAR2와 동일

- 오라클에서는 VARCHAR2 사용을 권고함

- VARCHAR와 2는 내부적으로도 똑같은데 ORACLE사에서 2를 쓰라고 얘기함 (왜인진모름)

 

 

(4)LONG

 

정수가 소숫점이 없을까? NO
고정소숫점이 정수의 정의.
2750이라는 정수에서 소숫점의 위치가 유효숫자 끝자리에 고정되어있다. 2750v 이부분!

실수는 소숫점이 잇는수 즉 가변소숫점임.
FLOATING POINT (부유하는 포인트)
즉 소숫점이 원하는 위치에 떠다닌다는 뜻

- 자바의 LONG과 다르다. 자바의 LONG은 정수연산시 8BYTE... 이지만

  오라클의 LONG은 문자임. 가변길이 문자열을 저장

- 최대 2GBYTE까지 저장 가능.

- 지금은 기능개선서비스가 정지됨

  왜? 한 테이블에 하나의 컬럼에서만 LONG타입을 사용할 수 있기 때문에

- LONG 대신 CLOB 사용을 권고

- SELECT문의 SELECT절, UPDATE문의 SET절, INSERT문의 VALUES 절에서 사용가능 (기능이 제한되어있다.)

 

*사용형식

컬럼명 LONG

  -길이지정을 하지않는다. (자동으로 2GB까지 할당)

 

 

EX

CREATE TABLE TEMP03(
    COL1 long,
    COL2 varchar2(4000),
    COL3 long
);

오류남 :

ORA-01754: a table may contain only one column of type LONG
01754. 00000 -  "a table may contain only one column of type LONG"

long타입 두개는 쓸수없음

 

CREATE TABLE TEMP03(
    COL1 long,
    COL2 varchar2(4000)
);

나머지는 가변길이데이터 (VARCHAR2)와 같은 성질임

INSERT INTO TEMP03(COL1,COL2)
    VALUES('IL POSTINO','BOYHOOD');

저장되어진 글자수만큼 저장하고 나머지는 반환했다.

 

 

(5) CLOB

 

- LOB (LARGE OBJECTS의 약자) 타입의 가변길이 문자열 저장

- C는 캐릭터 (B는 바이너리 (2진자료 주로 처리, 사진이나 이미지 동영상이 저장되어질때 이진자료))

- 대용량문자열자료를 처리하기위함이 CLOB

- 4GBYTE까지 처리가능함 

- 사용하는 컬럼에 제한이 없음

- 워낙 커다랗기때문에 일부 기능은 DBMS API의 함수를 사용해야 함

  (LENGTHB(바이트수)등은 사용불가 *LENGTH는 글자수이므로 쓸수있음)

 

*사용형식

컬럼명 CLOB

 

EX

CREATE TABLE TEMP04(
    COL1 CLOB,
    COL2 LONG,
    COL3 VARCHAR2(2000));
INSERT INTO TEMP04(COL1,COL2,COL3)
    VALUES('대한민국은 민주 공화국이다','대전시 중구 대흥동 500','ABCDEFG');

 

SELECT DBMS_LOB.SUBSTR(COL1,5,2) AS "COL1",
        DBMS_LOB.GETLENGTH(COL1) AS "COL2",
        LENGTH(COL3)
FROM TEMP04;

*SUBSTR : 문자열 함수중 자주사용됨
주어진 문자열에서 특정 문자열을 뽑아내는것
EX) 주민번호 7자리중에 성별나타내는 자릿수 하나만 떼는 방법
SUBSTR을 쓰기위해선 3개가 필요. (잘라낼원본,시작위치,갯수)
원래대로면 "은 " 이지만, DBMS_LOB타입에 사용되는 SUBSTR은 시작위치와 갯수의 위치가 다름

*Oracle은 문자에 숫자 부여할때 1번부터 java는 0번부터!
*java에도 substr이 있음. 사용방법이 좀 다름
*문자열에서 떼어넨 문자도 문자열임

 

AS 별칭은 테이블과 컬럼에 붙는다.