25.03.14 (금) 24일차 DB

허배령·2025년 3월 14일

괴발개발 TIL

목록 보기
29/54

ALTER (바꾸다, 수정하다, 변조하다)

-- 테이블에서 수정할 수 있는 것
1. 제약 조건(추가/삭제) -- 수정이 안돼서 수정하려면 삭제하고 추가
2. 컬럼(추가/수정/삭제) -- 가능은 하나 웬만하면 처음부터 잘 짓기
3. 이름변경 (테이블명, 컬럼명..)

1. 제약 조건(추가/삭제)

-- [작성법]
-- 1) 추가 : ALTER TABLE 테이블명
--			ADD [CONSTRAINT 제약조건명] 제약조건(지정할컬럼명)
--			[REFERENCES 테이블명[(컬럼명)]]; <-- FK 인 경우 추가


-- 2) 삭제 : ALTER TABLE 테이블명 DROP CONSTRAINT 제약조건명;

-- * 제약조건 자체를 수정하는 구문은 별도 존재하지 않음!
--> 삭제 후 추가를 해야함.
-- DEPARTMENT 테이블 복사 (컬럼명, 데이터타입, NOT NULL만 복사)
CREATE TABLE DEPT_COPY
AS SELECT * FROM DEPARTMENT;

SELECT * FROM DEPT_COPY;

-- DEPT_COPY의 DEPT_TITLE 컬럼에 UNIQUE 추가
ALTER TABLE DEPT_COPY 
ADD CONSTRAINT DEPT_COPY_TITLE_U UNIQUE(DEPT_TITLE);

-- DEPT_COPY의 DEPT_TITLE 컬렘에 UNIQUE 삭제
ALTER TABLE DEPT_COPY 
DROP CONSTRAINT DEPT_COPY_TITLE_U; -- 오라클에서 지어준 랜덤이름은 찾아서 삭제해줘야 함

-- *** DEPT_COPY의 DEPT_TITLE 컬럼에 NOT NULL 제약조건 추가 / 삭제 ***
ALTER TABLE DEPT_COPY
ADD CONSTRAINT DEPT_COPY_TITLE_NN NOT NULL(DEPT_TITLE);
--> NOT NULL 제약조건은 새로운 조건을 추가하는 것이 아닌
-- 컬럼 자체에 NULL을 허용 / 비허용을 제어하는 성질 변경의 형태로 인식됨.

-- MODIFY (수정하다) 구문을 사용해서 NULL 제어
ALTER TABLE DEPT_COPY
MODIFY DEPT_TITLE NOT NULL; -- DEPT_TITLE 컬럼에 NOT NULL 작용

ALTER TABLE DEPT_COPY
MODIFY DEPT_TITLE NULL; -- DEPT_TITLE 컬럼에 NULL 허용

2. 컬럼 (추가/수정/삭제)

-- 컬럼 추가
-- ALTER TABLE 테이블명 ADD(컬럼명 데이터타입 [DEFAULT '값']);


-- 컬럼 수정
-- ALTER TABLE 테이블명 MODIFY 컬럼명 데이터타입; --> 데이터 타입 변경

-- ALTER TABLE 테이블명 MODIFY 컬럼명 DEFAULT '값'; --> DEFAULT 값 변경


-- 컬럼 삭제
-- ALTER TABLE 테이블명 DROP (삭제할컬럼명);
-- ALTER TABLE 테이블명 DROP COLUMN 삭제할컬럼명;
-- CNAME 컬럼 추가
ALTER TABLE DEPT_COPY ADD (CNAME VARCHAR2(30));
-- 새로 추가한 컬럼에 있는 값은 NULL

-- LNAME 컬럼 추가 (기본값 '한국')
ALTER TABLE DEPT_COPY ADD (LNAME VARCHAR2(30) DEFAULT '한국');
--> 컬럼이 생성되면서 DEFAULT 값이 자동 삽입되어있음

-- D10 개발 1팀 추가
INSERT INTO DEPT_COPY
VALUES('D10', '개발1팀', 'L1', NULL, DEFAULT);
-- ORA-12899: "KH"."DEPT_COPY"."DEPT_ID" 열에 대한 값이 너무 큼(실제: 3, 최대값: 2)
--> DEPT_ID의 데이터타입이 CHAR(2) 이므로 영어+숫자 2글자까지 저장 가능
--> D10은 3바이트. CHAR(2) 들어올 수 없음
--> VARCHAR2(3)으로 변경해보기 (남는 바이트 메모리 반환 위해!)

-- DEPT_ID 컬럼 데이터 타입 수정
ALTER TABLE DEPT_COPY MODIFY DEPT_ID VARCHAR2(3)
--> 컬럼 데이터 타입 수정 후 다시 위 INSERT 실행 -> 삽입 성공 확인!

-- LNAME의 기본값을 'KOREA' 로 수정
ALTER TABLE DEPT_COPY MODIFY LNAME DEFAULT 'KOREA'; -- 오류
--> !! 기본값을 변경했다고 해서 기존 데이터가 변하지는 않음!
--> 앞으로 INSERT 될 데이터만 변경된 내용으로 삽입됨.

-- LNAME '한국' -> 'KOREA' 변경
UPDATE DEPT_COPY
SET LNAME = DEFAULT
WHERE LNAME = '한국';

-- DEPT_COPY 모든 컬럼 삭제
ALTER TABLE DEPT_COPY DROP (LNAME); -- LNAME 컬럼 사라짐
ALTER TABLE DEPT_COPY DROP COLUMN CNAME; -- CNAME 컬럼도 사라짐
ALTER TABLE DEPT_COPY DROP COLUMN LOCATION_ID; -- 사라짐..
ALTER TABLE DEPT_COPY DROP COLUMN DEPT_TITLE; -- 사라짐..

ALTER TABLE DEPT_COPY DROP COLUMN DEPT_ID; -- 오류 뜨며 삭제 안됨!!

-- 왜냐하면?
-- 컬럼 삭제 시 유의사항!
-- 테이블이란, 행과 열로 이루어진 DB의 가장 기본적인 객체.
-- 그러므로 최소 1개 이상의 컬럼이 존재해야하기 때문에
-- 모든 컬럼을 다 삭제할 순 없다!

-- 테이블 삭제
DROP TABLE DEPT_COPY; -- 테이블 삭제됨!
SELECT * FROM DEPT_COPY;
-- ORA-00942: 테이블 또는 뷰가 존재하지 않습니다

-- DEPARTMENT 테이블 복사해서 DEPT_COPY 생성
CREATE TABLE DEPT_COPY
AS SELECT * FROM DEPARTMENT;
--> 컬럼명, 데이터타입, NOT NULL 여부만 복사

-- DEPT_COPY 테이블에 PK 추가 
-- (컬럼 : DEPT_ID, 제약조건명 : D_COPY_PK)
ALTER TABLE DEPT_COPY
ADD CONSTRAINT D_COPY_PK PRIMARY KEY(DEPT_ID);

3. 이름 변경 (컬럼명, 테이블명, 제약조건명)

-- 1) 컬럼명 변경 (DEPT_TITLE -> DEPT_NAME) RENAME 변경할거 변경할거이름 TO 변경될이름
ALTER TABLE DEPT_COPY 
RENAME COLUMN DEPT_TITLE TO DEPT_NAME;

SELECT * FROM DEPT_COPY;

-- 2) 제약조건명 변경 (D_COPY_PK -> DEPT_COPY_PK)
ALTER TABLE DEPT_COPY
RENAME CONSTRAINT D_COPY_PK TO DEPT_COPY_PK;

-- 3) 테이블명 변경 (DEPT_COPY -> DCOPY)
ALTER TABLE DEPT_COPY
RENAME TO DCOPY;

SELECT * FROM DEPT_COPY;
-- ORA-00942: 테이블 또는 뷰가 존재하지 않습니다.
SELECT * FROM DCOPY;

DROP (테이블 삭제)

-- DROP TABLE 테이블명 [CASCADE CONSTRAINTS];
-- 제약조건이 걸려있어 관계형성이 되어있는 테이블 삭제 방법임.
-- 1) 관계가 형성되지 않은 테이블 삭제
DROP TABLE DCOPY;
-- ORA-00942: 테이블 또는 뷰가 존재하지 않습니다

-- 2) 관계가 형성된 테이블 삭제
CREATE TABLE TB1(
	TB1_PK NUMBER PRIMARY KEY,
	TB1_COL NUMBER
); -- 부모 테이블
SELECT * FROM TB1;

CREATE TABLE TB2(
	TB2_PK NUMBER PRIMARY KEY,
	TB2_COL NUMBER REFERENCES TB1 --() 자동참조 해주면 알아서 PRIMARY KEY로!
); -- 자식 테이블
SELECT * FROM TB2;

-- TB1에 샘플 데이터 삽입
INSERT INTO TB1 VALUES(1, 100);
INSERT INTO TB1 VALUES(2, 200);
INSERT INTO TB1 VALUES(3, 300);

-- TB2에 샘플  데이터 삽입
INSERT INTO TB2 VALUES(11, 1);
INSERT INTO TB2 VALUES(12, 2);
INSERT INTO TB2 VALUES(13, 3);

COMMIT;
-- TB1과 TB2는 부모-자식 테이블 관계 형성된 상태

-- 부모인 TB1 테이블을 삭제하려고 할 때
DROP TABLE TB1;
-- ORA-02449: 외래 키에 의해 참조되는 고유/기본 키가 테이블에 있습니다
-- 너 자식테이블 있어서 삭제 못해!
--> 해결 방법
-- 1) 자식을 먼저 없앤 후 부모 삭제
-- 2) ALTER 를 이용해서 FK 제약조건 삭제 후 TB1(부모) 삭제
-- 3) DROP TABLE 삭제옵션 CASCADE CONSTRAINTS 사용
--> CASCADE DONSTRAINTS : 삭제하려는 테이블과 연결된 FK 제약조건을 모두 삭제

DROP TABLE TB1 CASCADE CONSTRAINTS; -- 테이블 삭제 시 FK관계도 모두 삭제
SELECT * FROM TB1;
-- ORA-00942: 테이블 또는 뷰가 존재하지 않습니다

SELECT * FROM TB2; -- TB2 테이블만 아무 관계없이 남게 됨.

/* DDL 주의 사항 */
-- 1. DDL은 COMMIT / ROLLBACK 이 되지 않는다.
-- 2. DDL과 DML 구문 섞어서 수행하면 안된다!
--	DDL(CREATE, ALTER, DROP : 객체 생성/수정/삭제)
--	DML(INSERT, UPDATE, DELETE : 데이터(행) 추가/갱신/삭제)
--> DDL은 수행 시 존재하고 있는 트랜잭션을 모두 DB에 강제 COMMIT 시킴
--> DDL이 종료된 후 DML 구문을 수행할 수 있도록 권장!
COMMIT;
-- EX)
-- DML (INSERT)
INSERT INTO TB2 VALUES(14, 4);
INSERT INTO TB2 VALUES(15, 5);

-- DDL (컬럼명 변경)
ALTER TABLE TB2 RENAME COLUMN TB2_COL TO TB2_COLUMN; -- 강제커밋

ROLLBACK; -- ROLLBACK 안됨 ( 14,4 15,5 롤백안됨!!)
--> 위에서 DDL 구문 중 ALTER를 사용해서
-- 그 시점에 강제 COMMIT 되었기 때문에!!

VIEW

  • 논리적 가상 테이블
    -> 테이블 모양을 하고는 있지만, 실제로 값을 저장하고 있진 않음.

  • SELECT문의 실행 결과(RESULT SET)를 저장하는 객체

VIEW 사용 목적

  • 1) 복잡한 SELECT문을 쉽게 재사용하기 위해.
  • 2) 테이블의 진짜 모습을 감출 수 있어 보안상 유리.

VIEW 사용 시 주의 사항

  • 1) 가상의 테이블(실체 X)이기 때문에 ALTER 구문 사용 불가.
  • 2) VIEW를 이용한 DML(INSERT,UPDATE,DELETE)이 가능한 경우도 있지만
    제약이 많이 따르기 때문에 조회(SELECT) 용도로 대부분 사용.
- VIEW 작성법 
 CREATE [OR REPLACE] [FORCE | NOFORCE] VIEW 뷰이름 [컬럼 별칭]
 AS 서브쿼리(SELECT)
 [WITH CHECK OPTION]
 [WITH READ OLNY];

1) OR REPLACE 옵션 : 
	기존에 동일한 이름의 VIEW가 존재하면 이를 변경
	없으면 새로 생성

2) FORCE | NOFORCE 옵션 : 
	FORCE : 서브쿼리에 사용된 테이블이 존재하지 않아도 뷰 생성
	NOFORCE(기본값): 서브쿼리에 사용된 테이블이 존재해야만 뷰 생성
   
3) 컬럼 별칭 옵션 : 조회되는 VIEW의 컬럼명을 지정

4) WITH CHECK OPTION 옵션 : 
	옵션을 지정한 컬럼의 값을 수정 불가능하게 함.

5) WITH READ OLNY 옵션 :
	뷰에 대해 SELECT만 가능하도록 지정.
VIEW 를 생성하기 위해서는 권한이 필요하다!

-- (SYS 관리자 계정 접속)
ALTER SESSION SET "_ORACLE_SCRIPT" = TRUE;
--> 계정명이 언급되는 상황에서는 이 구문 필수적으로 진행!
-- C## 안 붙이겠다.

-- VIEW 생성 권한 부여
GRANT CREATE VIEW TO kh;

CREATE VIEW V_EMP
AS SELECT * FROM EMPLOYEE;
-- ORA-01031: 권한이 불충분합니다. (SYS관리자 계정 접속 전!!)
-- 위 구문 마치고 다시 kh로 돌아와서 구문 실행!

--> VIEW 생성 구문 기초 문법!!!

SELECT * FROM V_EMP;

-- 사번, 이름, 부서명, 직급명 조회하기 위한 VIEW 생성
CREATE OR REPLACE VIEW V_EMP
AS
SELECT EMP_ID 사번, EMP_NAME 이름, 
NVL(DEPT_TITLE, '없음') 부서명, JOB_NAME 직급명
FROM EMPLOYEE
JOIN JOB USING (JOB_CODE)
LEFT JOIN DEPARTMENT ON (DEPT_CODE = DEPT_ID)
ORDER BY 사번 ASC;
-- ORA-00955: 기존의 객체가 이름을 사용하고 있습니다.
-- -> 오류를 고치기 위해 위에 CREATE OR RELACE VIEW로 바꿔줌

-- V_EMP에서 대리 직원들을 이름 오른차순으로 조회
-- VIEW 조회 결과로 보이는 컬럼명을 이용해야 한다!!
SELECT * FROM V_EMP -- 현재 상태가 위에서 바꿔놓은 형태임
WHERE 직급명 = '대리'
ORDER BY 이름;

/* VIEW를 이용해서 DML 사용하기 + 문제점 확인 */

-- DEPARTMENT 테이블을 복사한 DEPT_COPY2 생성(테이블로 생성 VIEW 말고 ㅋㅋ)
CREATE TABLE DEPT_COPY2
AS SELECT * FROM DEPARTMENT;

-- DEPT_COPY2 테이블에서 DEPT_ID, LOCATION_ID 컬럼만 이용해서
-- V_DCOPY2 VIEW 생성
CREATE OR REPLACE VIEW V_DCOPY2
AS SELECT DEPT_ID, LOCATION_ID 
FROM DEPT_COPY2;

-- V_DCOPY2 VIEW 생성 확인하기
SELECT * FROM V_DCOPY2;

-- 원본 테이블
SELECT * FROM DEPT_COPY2;

-- V_DCOPY2 VIEW를 이용해서 INSERT 수행
INSERT INTO V_DCOPY2
VALUES ('D0', 'L2');
-- 가상 테이블인 VIEW 인데도 INSERT가 성공함!

SELECT * FROM DEPT_COPY2;
-- D0, NULL, L2 삽입

-- VIEW에 INSERT를 수행했지만
-- VIEW 생성 시 사용한 원본 테이블에도
-- 값이 함께 INSERT 됨을 확인!!

--> 모든 컬럼 값이 INSERT 된 것이 아니라
-- VIEW를 생성할 때 사용된 컬럼에만 데이터가 삽입 되었고
-- 사용되지 않은 컬럼(DEPT_TITLE)에는 NULL이 들어감!
--> NULL은 DB의 무결성을 약하게 만드는 주요 원인이다!
--> 그러므로 가능하면 의도되지 않은 NULL은 존재하지 않게 해야 한다.
-->> 찐막으로 VIEW를 이용한 DML은 사용을 지양한다!!!!

/* 무결성 : 데이터베이스에서 데이터를 정확하고 일관되게
 * 				유지하기 위한 중요한 개념.
 * 
 * 데이터의 정확성, 일관성, 신뢰성을 보장함.
 */

/* WITH READ ONLY 옵션 사용하기 */
-- 왜 사용할까?
--> VIEW를 이용해서 DML(INSER/UPDATE/DELETE)을 막기 위해서!

CREATE OR REPLACE VIEW V_DCOPY2
AS SELECT DEPT_ID, LOCATION_ID
FROM DEPT_COPY2
WITH READ ONLY; -- 수행하면 읽기 전용

-- INSERT 수행
INSERT INTO V_DCOPY2
VALUES ('D0', 'L3');
-- ORA-42399: 읽기 전용 뷰에서는 DML 작업을 수행할 수 없습니다.

SEQUENCE (순서, 연속)

  • 순차적으로 일정한 간격의 숫자(번호)를 발생시키는 객체 (번호 생성기)
 *** SEQUENCE 왜 사용할까?? ***
PRIMARY KEY(기본키) : 테이블 내 각 행을 구별하는 식별자 역할
						 NOT NULL + UNIQUE의 의미를 가짐
 
  PK가 지정된 컬럼에 삽입될 값을 생성할 때 SEQUENCE를 이용하면 좋다!
  
  [작성법]
  CREATE SEQUENCE 시퀀스이름
  [START WITH 숫자] -- 처음 발생시킬 시작값 지정, 생략하면 1이 기본
  [INCREMENT BY 숫자] -- 다음 값에 대한 증가치, 생략하면 1이 기본
  [MAXVALUE 숫자 | NOMAXVALUE] -- 발생시킬 최대값 지정, 생략하면 기본값은 10^27 - 1 (즉, 매우 큰 값)입니다 / NOMAXVALUE를 사용하면 최대값 제한이 없음을 의미
  [MINVALUE 숫자 | NOMINVALUE] -- 최소값 지정 , 기본값은 -10^26 /  NOMINVALUE를 사용하면 최소값 제한이 없음을 의미
  [CYCLE | NOCYCLE] -- 값 순환 여부 지정 , 기본값은 NOCYCLE
		-- CYCLE: 값이 최대값에 도달하면 다시 최소값부터 순환
		-- NOCYCLE: 값을 순환하지 않고, 최대값에 도달하면 오류를 발생시킴
  
  [CACHE 시퀀스개수 | NOCACHE] -- 기본값은 20
	-- 시퀀스의 캐시 메모리는 할당된 크기만큼 미리 다음 값들을 생성해 저장해둠
	--> 시퀀스 호출 시 미리 저장되어진 값들을 가져와 반환하므로 
	--  매번 시퀀스를 생성해서 반환하는 것보다 DB속도가 향상됨.
 
 
  ** 사용법 **
 
1) 시퀀스명.NEXTVAL : 다음 시퀀스 번호를 얻어옴.
  					(INCREMENT BY 만큼 증가된 수), 생성 후 처음 호출된 시퀀스인 경우
 					START WITH에 작성된 값이 반환됨.
 
2) 시퀀스명.CURRVAL : 현재 시퀀스 번호를 얻어옴., 시퀀스가 생성 되자마자 호출할 경우 오류 발생.
  					== 마지막으로 호출한 NEXTVAL 값을 반환
시퀀스 생성하기

CREATE SEQUENCE SEQ_TEST_NO
START WITH 100 -- 시작번호 100
INCREMENT BY 5 -- NEXTVAL 호출 후 5씩 증가
MAXVALUE 150	 -- 증가 가능한 최대값이 150
NOMINVALUE		 -- 최소값 없음
NOCYCLE			 	 -- 반복 안함
NOCACHE;			 -- 미리 만들어둘 시퀀스 번호 없음
시퀀스 삭제하기 
DROP SEQUENCE SEQ_TEST_NO;

-- 시퀀스 테스트할 테이블 생성
CREATE TABLE TB_TEST(
	TEST_NO NUMBER PRIMARY KEY,
	TEST_NAME VARCHAR2(30) NOT NULL
);
-- 현재 시퀀스 번호 확인
SELECT SEQ_TEST_NO.CURRVAL FROM DUAL;
-- ORA-08002: 시퀀스 SEQ_TEST_NO.CURRVAL은 이 세션에서는 정의 되어 있지 않습니다.
--> CURRVAL의 정확한 의미는
-- 가장 최근 호출된 NEXTVAL의 값을 반환함을 뜻함
--> NEXTVAL을 호출한 적이 없어서 오류 발생!

--> 해결방법 : NEXTVAL 호출하기
SELECT SEQ_TEST_NO.NEXTVAL FROM DUAL;
-- 시퀀스 생성 후 첫 NEXTVAL == START WITH 값인 100

SELECT SEQ_TEST_NO.CURRVAL FROM DUAL; -- 100
-- 가장 최근 호출한 NEXTVAL 값이 100이니까!

-- NEXTVAL 을 호출할 때마다
-- INCREMENT BY 에 작성된 수만큼 증가하는지 확인
SELECT SEQ_TEST_NO.NEXTVAL FROM DUAL;
-- 처음 : 100
-- 1회 : 105
-- 2회 : 110

-- TB_TEST 테이블에 PK값을 SEQ_TEST_NO 시퀀스로 생성하기
INSERT INTO TB_TEST
VALUES (SEQ_TEST_NO.NEXTVAL, '짱구'); -- 125

INSERT INTO TB_TEST
VALUES (SEQ_TEST_NO.NEXTVAL, '철수'); -- 130

INSERT INTO TB_TEST
VALUES (SEQ_TEST_NO.NEXTVAL, '유리'); -- 135

-- UPDATE 에서 시퀀스 사용하기
-- '짱구'의 PK 컬럼값을
-- SEQ_TEST_NO 시퀀스의 다음 생성값으로 변경하기
UPDATE TB_TEST
SET TEST_NO = SEQ_TEST_NO.NEXTVAL
WHERE TEST_NAME = '짱구';
-- ORA-08004: 시퀀스 SEQ_TEST_NO.NEXTVAL exceeds MAXVALUES
--> MAXVALUE 150 보다 더 증가할 수 없다!

SELECT * FROM TB_TEST;

-- SEQUENCE 변경 (ALTER)
--> START WITH 빼고 모두 변경 가능!!

[작성법]
ALTER SEQUENCE 시퀀스이름
[INCREMENT BY 숫자]
[MAXVALUE 숫자 | NOMAXVALUE]
[MINVALUE 숫자 | NOMINVALUE]
[CYCLE | NOCYCLE]
[CACHE 숫자 | NOCACHE]

-- SEQ_TEST_NO 의 MAXVALUE 값을 200으로 수정
ALTER SEQUENCE SEQ_TEST_NO
MAXVALUE 200; -- 200까지 증가 ㅋㅋ

-- 200까지 증가 시켜서 변경확인
SELECT SEQ_TEST_NO.NEXTVAL FROM DUAL;
-- VIEW, SEQUENCE 삭제

-- V_DCOPY2 VIEW 삭제
DROP VIEW V_DCOPY2;

-- SEQ_TEST_NO SEQUENCE 삭제
DROP SEQUENCE SEQ_TEST_NO;

INDEX (색인)

  • SQL 구문 중 SELECT 처리 속도를 향상 시키기 위해
    컬럼에 대하여 생성하는 객체

  • 인덱스 내부 구조는 B* 트리(B-star tree) 형식으로 되어있음.

[작성법]
CREATE [UNIQUE] INDEX 인덱스명
ON 테이블명 (컬럼명[, 컬럼명 | 함수명]);

DROP INDEX 인덱스명;

INDEX의 장점

  • 이진 트리 형식으로 구성되어 자동 정렬 및 검색 속도 증가.

  • 조회 시 테이블의 전체 내용을 확인하며 조회하는 것이 아닌
    인덱스가 지정된 컬럼만을 이용해서 조회하기 때문에
    시스템의 부하가 낮아짐.

INDEX의 단점

  • 데이터 변경(INSERT,UPDATE,DELETE) 작업 시 이진 트리 구조에 변형이 일어남
    -> DML 작업이 빈번한 경우 시스템 부하가 늘어 성능이 저하됨.

  • 인덱스도 하나의 객체이다 보니 별도 저장공간이 필요(메모리 소비)

  • 인덱스 생성 시간이 필요함.

인덱스가 자동 생성되는 경우

  • PK ,FK, UNIQUE 제약조건이 설정된 컬럼에 대해 UNIQUE INDEX가 자동 생성된다.

  • PK에 자동 생성되는 이유 : 기본 키는 중복을 허용하지 않고, NOT NULL이어야 하기 때문이다.

  • UNIQUE 제약조건 설정 컬럼에서 자동생성 되는 이유 : 중복을 허용하지 않는 고유 값을 보장해야 하기 때문이다.

SELECT ROWID, EMP_ID, EMP_NAME
FROM EMPLOYEE;
-- ROWID : 오라클에서 각 행의 고유한 주소를 나타내는 가상 컬럼(물리적 주소)
-- 인덱스가 ROWID 저장함.
-- 인덱스는 컬럼의 값과 해당행의 ROWID를 매핑해서 저장함.
-- 컬럼값 -> 해당 행의 ROWID를 빠르게 찾아낼 수 있다!

-- 현재 사용자에 생성된 인덱스 목록 조회
SELECT INDEX_NAME, TABLE_NAME, 
UNIQUENESS, STATUS
FROM USER_INDEXES;

-- EMPLOYEE 테이블의 EMP_NAME 컬럼에 인덱스 생성
CREATE INDEX IDX_EMP_NAME
ON EMPLOYEE (EMP_NAME);
--> EMPLOYEE 테이블의 EMP_NAME 컬럼에 대해 빠른 검색이 가능

/*
 * 인덱스명 : IDX_EMP_NAME
 * 테이블명 : EMPLOYEE
 * 컬럼명  : EMP_NAME
 * 목적 : EMP_NAME 이용한 컬럼 검색 속도 향상
 * */

-- EMPLOYEE 테이블의 EMAIL 컬럼에 UNIQUE INDEX 생성
CREATE UNIQUE INDEX IDX_UNIQUE_EMAIL
ON EMPLOYEE (EMAIL);

-- UNIQUE INDEX 는 중복 방지
-- EMIAL 컬럼에 중복되지 않는 고유한 값만 허용
--> 중복된 EMAIL 삽입 시 오류 발생!
-- 인덱스 성능 확인용 테이블 생성
CREATE TABLE TB_IDX_TEST (
	TEST_NO NUMBER PRIMARY KEY, -- 자동으로 UNIQUE INDEX 생성됨
	TEST_ID VARCHAR2(20) NOT NULL
);


-- TB_IDX_TEST 테이블에
-- 샘플데이터 100만개 삽입 (PL/SQL 사용)
-- * PL/SQL 이란?  
-- 오라클 데이터베이스에서 사용하는 절차적 확장 언어.
-- 변수, 조건문(IF/CASE), 반복문(LOOP, WHILE) 사용 가능
BEGIN 
	FOR I IN 1..1000000 -- I 는 1부터 100만까지 반복
	LOOP
		INSERT INTO TB_IDX_TEST
		VALUES(I, 'TEST' || I);
	END LOOP;
	
	COMMIT; -- 모든 삽입 작업을 커밋
END;


SELECT COUNT(*) FROM TB_IDX_TEST; -- 100만개 행이 삽입됨을 확인

-- 인덱스를 사용해서 검색하는 방법
--> WHERE 절에 INDEX가 적용된 컬럼을 언급하기

/* 인덱스 X */
-- TEST_ID 가 'TEST500000' 인 행 조회하기
SELECT * FROM TB_IDX_TEST
WHERE TEST_ID = 'TEST500000'; -- 0.030s


/* 인덱스 O */
-- TEST_NO가 500000인 행을 조회하기
SELECT * FROM TB_IDX_TEST
WHERE TEST_NO = 500000; -- 0.001s

-- 보통 10~30배 차이
profile
인생은 변수

0개의 댓글