Database
CREATE TABLE 테이블명 (
컬럼명 데이터타입 [CONSTRAINT 제약조건별칭] 제약조건,
컬럼명 데이터타입 [CONSTRAINT 제약조건별칭] 제약조건,
...
);
CREATE TABLE 테이블명 (
컬럼명 데이터타입,
컬럼명 데이터타입,
...,
[CONSTRAINT 제약조건별칭] 제약조건 (컬럼명),
[CONSTRAINT 제약조건별칭] 제약조건 (컬럼명, 컬럼명, ...)
);
-- 하나 이상의 컬럼을 조합하여 제약조건을 정의할 수 있다.
-- NOT NULL 제약조건을 제외한 모든 제약조건을 정의할 수 있다.
제약조건 정의하기
CREATE TABLE users (
user_name varchar2(30) NOT NULL,
user_tel varchar2(20) CONSTRAINT user_tel_nn NOT NULL,
...
);
-- NOT NULL 제약조건이 정의되지 않은 컬럼은 기본적으로 NULL 값을 가질 수 있다.
UNIQUE 제약조건 정의
CREATE TABLLE users (
user_name varchar2(30),
user_tel varchar2(20) CONSTRAINT user_tel_nn NOT NULL,
user_email varchar2(200) CONSTRAINT user_email_uk UNIQUE,
...,
CONSTRAINT user_tel_uk UNIQUE(user_tel)
);
-- user_tel 컬럼은 NOT NULL, UNIQUE 제약조건이 정의되어 있음
-- user_tel의 NOT NULL제약조건은 컬럼 레벨 제약조건 방식으로 정의 UNIQUE제약조건은 테이블 레벨 제약조건 방식으로 정의했음
-- user_email 컬럼은 UNIQUE 제약조건이 정의되어 있음, NULL값이 허용됨
PRIMARY KEY 제약조건 정의
CREATE TABLE users (
user_no number(10) CONSTRAINT user_no_pk PRIMAY KEY,
...
);
CREATE TABLE users (
user_no number(10),
...,
CONSTRAINT user_no_pk PRIMARY KEY(user_no)
);
CREATE TABLE course_registerations (
stud_no number(10),
course_no number(5),
...,
CONSTRAINT course_regist_pk PRIMARY KEY(stud_no, course_no)
);
-- 하나 이상의 열을 조합해서 기본키 제약조건 정의하기
FOREIGN KEY 제약조건
CREATE TABLE emps(
...
dept_id number(10) CONSTRAINT emp_dept_id_fk REFERENCES depts(dept_id),
...
);
-- emps 테이블의 dept_id 컬럼의 값은 depts테이블의 dept_id 값을 참조한다.
CREATE TABLE emps(
...
dept_id number(10),
...,
CONSTRAINT emp_dept_id_fk FOREIGN KEY (dept_id) REFERENCES depts(dept_id),
);
-- REFERENCES 키워드와 참조대상테이블(컬럼명)을 지정한다.
-- 참조대상 컬럼은 PRIMARY KEY 혹은 UNIQUE 제약조건이 정의된 컬럼만 가능하다.
CHECK 제약 조건
CREATE TABLE products (
...
pro_price number(10) CONSTRAINT pro_price_ck CHECK (pro_price > 0),
pro_sell varchar2(20) CONSTRAINT pro_sell_ck CHECK (pro_sell in ('판매중', '재고부족', '절판')),
pro_discount number(4, 3) CONSTRAINT pro_discount_ck CHECK (pro_discount >= 0.0 and pro_discount <= 0.5),
);
-- 제약조건 정의하기
-- 컬럼레벨 제약조건 정의방식 사용
-- 별칭은 30자를 넘으면 안된다.
CREATE TABLE sample_todos (
todo_no NUMBER(8)
CONSTRAINT sampletodos_no_pk PRIMARY KEY,
todo_title VARCHAR2(250) NOT NULL,
todo_writer VARCHAR2(20)
CONSTRAINT sampletodos_writer_fk REFERENCES sample_users (user_id),
todo_day DATE NOT NULL,
todo_status VARCHAR2(10) DEFAULT '등록'
CONSTRAINT sampletodos_status_ck CHECK (todo_status in ('등록', '삭제', '완료')),
todo_text VARCHAR2(1000)
CONSTRAINT sampletodos_text_nn NOT NULL,
todo_created_Date DATE DEFAULT SYSDATE,
todo_completed_date DATE,
todo_deleted_date DATE
);
-- 생성된 테이블 삭제하기
DROP TABLE sample_todos;
commit;
-- 테이블 레벨 제약조건 정의방식
CREATE TABLE sample_todos (
todo_no NUMBER(8),
todo_title VARCHAR2(250) NOT NULL,
todo_writer VARCHAR2(20) NOT NULL,
todo_day DATE NOT NULL,
todo_status VARCHAR2(10) DEFAULT '등록',
todo_text VARCHAR2(1000) NOT NULL,
todo_created_Date DATE DEFAULT SYSDATE,
todo_completed_date DATE,
todo_deleted_date DATE,
CONSTRAINT sampletodos_no_pk PRIMARY KEY (todo_no),
CONSTRAINT sampletodos_writer_fk FOREIGN KEY (todo_writer) REFERENCES sample_users (user_id),
CONSTRAINT sampletodos_status_ck CHECK (todo_status in ('등록', '삭제', '완료'))
);
-- 상품을 여러 개 담을 수 있는 장바구니 테이블 정의하기
CREATE TABLE sample_cart_items (
item_no NUMBER(8) CONSTRAINT cartitems_no_pk PRIMARY KEY,
user_id VARCHAR2(20) NOT NULL,
product_no NUMBER(8) NOT NULL,
item_amount NUMBER(4) DEFAULT 1,
item_created_date DATE DEFAULT SYSDATE,
CONSTRAINT cartitems_userid_fk FOREIGN KEY (user_id) REFERENCES sample_users (user_id),
CONSTRAINT cartitems_productno_fk FOREIGN KEY (product_no) REFERENCES sample_products (product_no),
CONSTRAINT cartitems_uk UNIQUE (user_id, product_no),
CONSTRAINT cartitems_amount_ck CHECK (item_amount >= 1)
);
CREATE SEQUENCE cartitem_seq NOCACHE;
CREATE SEQUENCE todo_seq NOCACHE;
-- sample_cart_items 테이블에 장바구니 상품정보 추가하기
INSERT INTO sample_cart_items (item_no, user_id, product_no, item_amount, item_created_date)
VALUES (cartitem_seq.nextval, 'hong', 20, 1, sysdate);
DELETE FROM sample_cart_items;
commit;
-- sample_products 테이블에서 20번 상품 삭제하기
DELETE FROM sample_products
WHERE product_no = 20;
-- 오류 발생 ORA-02292: integrity constraint (HR.CARTITEMS_PRODUCTNO_FK) violated - child record found
-- sample_products테이블의 20번 상품을 참조하는 행이 sample_cart_items 테이블에
-- 존재하고 있기 때문에 20번 상품은 삭제할 수 없다.
-- sample_cart_items의 상품수량을 변경하기
UPDATE sample_cart_items
SET
item_amount = 0
WHERE item_no = 5;
-- 오류 발생 ORA-02290: check constraint (HR.CARTITEMS_AMOUNT_CK) violated
-- item_amount에 정의되어 있는 CHECK 제약조건 위배.
CREATE INDEX 인덱스명
ON 테이블명 (컬럼명, ....)
DROP INDEX 인덱스명
CREATE INDEX 인덱스명
ON 테이블명 (오라클함수)
-- 인덱스 생성하기
-- sample_users 테이블의 user_phone컬럼의 값으로 사용자를 조회하는 일이 빈번하게 있다
-- 전화번호로 사용자를 빠르게 검색할 수 있도록 user_phone컬럼의 값으로 인덱스(색인)을 생성하기
-- sample_user_phone_idx의 내용
-- user_phone rowid
------------------------------------------
-- 010-0001-0001 AAAAAA AAE AAAACT AAA
-- 010-0001-0002 AAAAAA AAE AAAACT AAE
-- 010-0001-0011 AAAAAA AAE AAAACT ABA
-- 010-0001-0291 AAAAAA AAE AAAACT AAZ
-- 010-0001-1234 AAAAAA AAE AAAACT AZA
-- 010-0001-1256 AAAAAA AAE AAAACT AZZ
CREATE INDEX sample_user_phone_idx
ON sample_users (user_phone);
DROP INDEX sample_user_phone_idx;
-- sample_users 테이블에서 user_phone 컬럼의 값이 where절의 조회조건으로 사용되면
-- 자동으로 sample_user_phone_idx 인덱스(색인)에서 해당전화번호의 ROWID를 사용해서
-- 사용자정보(데이터행)를 빠르게 검색한다
SELECT *
FROM sample_users
WHERE user_phone = '010-5678-1234';
-- Top-N 분석과 분석함수 사용하기
-- Top-N 분석하기 : rownum을 사용한다.
-- 월급에 대한 내림차순으로 정렬했을 때, 급여를 가장 많이 받은 사람 3명의 아이디, 이름, 급여 조회
SELECT employee_id, first_name, salary
FROM (SELECT employee_id, first_name, salary
FROM employees
ORDER BY salary desc)
WHERE rownum <= 3;
-- 분석함수
-- rank(), dense_rank(), row_number()
-- SELECT 분석함수() OVER ([PARTITION BY 컬럼] [ORDER BY 컬럼]), 컬럼, 컬럼, 컬럼
-- FROM 테이블명
-- rank(), dense_rank(), row_number()으로 랭킹, 순번 부여하기
SELECT RANK() OVER (ORDER BY salary DESC) ranking,
DENSE_RANK() OVER (ORDER BY salary DESC) dense_ranking,
ROW_NUMBER() OVER (ORDER BY salary DESC) row_number,
employee_id, first_name, salary
FROM employees;
-- 각 부서에서 급여를 가장 많이 받는 사람 조회하기
SELECT department_id, employee_id, first_name, salary
FROM (SELECT RANK() OVER (PARTITION BY department_id ORDER BY salary DESC) ranking,
employee_id, first_name, department_id, salary
FROM employees
ORDER BY department_id, salary DESC)
WHERE ranking = 1
AND department_id IS NOT NULL;
-- 입사년도별 급여를 가장 많이 받는 사람 조회하기
SELECT hire_year, employee_id, first_name, salary
FROM (SELECT RANK() OVER(partition by to_char(hire_date, 'yyyy') ORDER BY salary DESC) ranking,
TO_CHAR(hire_date, 'yyyy') hire_year, employee_id, first_name, salary
FROM employees)
WHERE ranking = 1;
-- row_number() 분석함수를 사용해서 순번을 부여하고, 특정 범위의 데이터를 조회하기
-- 데이터에 대한 페이징처리시 사용되는 쿼리문
SELECT row_number, employee_id, first_name
FROM (SELECT ROW_NUMBER() OVER (ORDER BY employee_id) row_number, employee_id, first_name
FROM employees)
WHERE row_number >= (? - 1) * 10 + 1 and row_number <= ? * 10;