CREATE DATABASE 데이터베이스이름; // db 생성
DROP DATABASE 데이터베이스이름; // db 삭제
CREATE TABLE 테이블명 (
컬럼1이름 datatype,
컬럼2이름 datatype,
컬럼3이름 datatype,
...등
);
CREATE TABLE new_table (
id INT,
이름 VARCHAR(100),
나이 INT
);
CREATE TABLE new_table2 (
id INT,
이름 VARCHAR(100) DEFAULT '홍길동',
나이 INT
)
DROP TABLE 테이블명 // table 삭제
ALTER TABLE 테이블명 ADD 컬럼명 VARCHAR(100); // 컴럼 추가
ALTER TABLE 테이블명 MODIFY COLUMN 컬럼명 datatype; // 컬럼 데이터 타입 변경
ALTER TABLE 테이블명
DROP COLUMN 컬럼명;
Q1.
유저 이름, 전화번호를 저장할 테이블을 하나 만들어옵시다.
CREATE TABLE member (
id INT,
이름 VARCHAR(100),
연락처 VARCHAR(100)
)
Q2.
방금 만든 테이블에 '나이'를 저장할 컬럼을 추가해봅시다. 근데 기본값은 1로 설정해봅시다.
ALTER TABLE member
ADD 나이 INT DEFAULT 1;
Q3.
방금 만든 테이블의 '나이' 컬럼의 데이터타입을 변경해봅시다.
INT였던걸 BIGINT로 변경해봅시다.
ALTER TABLE member
MODIFY COLUMN 나이 BIGINT;
Q4.
부끄러우니까 방금 만든 테이블을 삭제해봅시다.
이것저것 클릭질 하지말고 SQL 작성하고 실행시켜서 삭제하십시오.
컬럼 만들 때 제약조건을 걸어둘 수 있다.
이 컬럼은 NOT NULL 해야한다 (텅빈 데이터 집어넣지 말아라)
이 컬럼에 있는 데이터들은 항상 UNIQUE 해야한다
여기에 음수말고 양수만 들어오는지 CHECK 하라
이 컬럼을 PRIMARY KEY로 설정하라
등 여러가지 설정이 가능하다.
CREATE TABLE new_table (
id INT NOT NULL,
이름 VARCHAR(100) NOT NULL,
나이 INT
)
CREATE TABLE new_table (
id INT UNIQUE,
이름 VARCHAR(100),
나이 INT
)
CREATE TABLE new_table (
id INT,
이름 VARCHAR(100),
나이 INT,
UNIQUE(이름, 나이)
)
DROP TABLE new_table; // *
CREATE TABLE new_table (
id INT,
이름 VARCHAR(100),
나이 INT CHECK (나이 > 0),
)
DROP TABLE new_table; // (제약 설명과 관련 없는 내용)
(테이블이 만들어져 있는데 이것저것 테스트한다고 생성하면 안되니까 시작 전에 테이블을 제거하고 다시 만드는 꿀팀)
컬럼만들 때 우측에 CHECK () 넣으면 컬럼에 들어갈 값에 제약을 둘 수 있다.
등호 부등호 AND OR 써서 조건식처럼 입력하면 됨, IN 연산자도 가능
CREATE TABLE new_table (
id INT PRIMARY KEY,
이름 VARCHAR(100),
나이 INT CHECK (나이 > 0),
)
CREATE TABLE new_table (
id INT AUTO_INCREMENT PRIMARY KEY,
이름 VARCHAR(100),
나이 INT,
)
CREATE TABLE new_table (
id INT,
이름 VARCHAR(100),
나이 INT,
PRIMARY KEY (id), // 제약조건 줄 때 밑에 이렇게 써도 됨
CHECK(나이 > 10)
)
CREATE TABLE new_table (
id INT,
이름 VARCHAR(100),
나이 INT,
CONSTRAINT 제약조건작명 PRIMARY KEY (id),
CONSTRAINT 제약조건작명2 CHECK(나이 > 10)
)
제1정규형 (1st normal form)
여러분은 지금부터 구민 체육센터 전산시스템 만드는 개발자입니다.
일단 체육센터에 수강 등록한 사람들을 테이블로 정리하고 싶은겁니다.
그래서 테이블 하나 만들어서 이쁘게 잘 저장을 해놨습니다.
근데 '김민수' 라는 사람이 다음 날 '골프초급'을 또 수강신청한겁니다.
그럼 어떻게 데이터를 추가하죠?
▲ 하나의 셀에 데이터를 더 추가하면 어떨까요.
그래도 되긴 합니다.
근데 보통은 이렇게 해놓으면 나중에 성능이슈가 생길 수 있습니다.
저렇게 문자로 길게 저장해두면 상품목록이 길어질 수록 찾기 / 수정 / 삭제 작업이 느려집니다.
엑셀에서도 저렇게 해놓으면 사수에게 빠따맞음
실은 JSON 데이터타입 아니면 array 데이터타입 (Postgres에서 가능) 사용하면
['헬스', '골프초급']
이런 식으로 여러개의 문자나 숫자를 한 칸에 저장할 수 있는데
그거 써도 마찬가지로 문제될 수 있습니다.
왜냐면 그냥 array, JSON은 문자와 취급이 비슷해서 나중에 array 자료 안의 일부 항목만 수정하는게 매우 어렵기 때문입니다.
(그래서 수정할 때는 새 값으로 아예 갈아치우거나 그런 식으로 많이 합니다)
▲ 그래서 이렇게 만드는게 낫습니다.
하나의 셀 안에는 하나의 데이터만 보관하는 겁니다.
이 작업이 완료된 테이블을 제1정규형 (1st normal form) 이라고 합니다.
이렇게 해두면 성능문제도 없어지고 나중에 다른 컬럼을 추가할 때도 문제가 안생길 수 있습니다.
(참고)
예전에 배운 비관계형 데이터베이스들은 제1 정규화를 안하는 경우가 있습니다.
하지만 관계형 데이터베이스는 제1 정규화 안해놓으면 단점이 많아서 데이터 저장할 때 항상 하도록 합시다.
제2정규형 (2nd normal form)
아까 제1정규화 해놓은 테이블이 있습니다.
심심해서 각 프로그램마다 '가격'이랑 '납부여부'를 기록하는 컬럼도 만들어놨습니다.
잘 돌아갈 것 같은데 근데 이런 문제가 생길 수도 있습니다.
100개 행을 고치는 불상사가 생기는게 싫다면
현재 테이블의 주제와 관련없는 컬럼은 다른 테이블로 옮기십시오.
'가격' 컬럼은 수강등록현황과 별로 상관이 없고 '프로그램' 종류에 따라서 결정될 뿐입니다.
그래서 '가격' 컬럼은 현재 테이블의 주제와 맞지 않기 때문에
그걸 잘라내서 새로운 테이블 만들어서 거기 넣어봤습니다.
이 작업이 완료된 테이블을 제2정규형 (2nd normal form) 이라고 합니다.
장점은 아까처럼 '헬스'의 가격이 수정되어야할 때 100곳을 수정할 필요가 없어짐
물론 이러면 단점도 있는데 나중에 김민수라는 사람이 얼마를 내야할지 조회하는게 귀찮아질 수 있는데
그건 나중에 SQL JOIN 문법 쓰면 됩니다.
제2정규형 - 어려운버전
제2정규형의 교과서적 정의는 partial dependency를 제거한 테이블입니다.
쉽게 설명해보자면
▲ 위의 테이블에선 (회원번호 + 프로그램) 이렇게 조합해야 primary key 역할을 수행할 수 있습니다.
'회원번호' 만으로 primary key 역할은 불가능합니다.
'프로그램' 만으로 primary key 역할은 불가능합니다.
근데 두개 합치면 primary key 역할 가능
두개 컬럼을 합친 primary key를 composite primary key 라고 합니다.
▲ 예를 들어 위의 테이블에서 보면 '가격' 컬럼은 '프로그램'에 따라서 결정될 뿐 '회원번호'과는 상관이 없습니다.
그 경우 가격 컬럼은 partial dependency가 있다고 표현합니다.
partial dependency가 있는 컬럼을 다른 테이블로 빼면 제2정규형 테이블
완성입니다.
그래서 위의 예시의 '가격' 컬럼을 다른 테이블로 빼는 것입니다.
위 테이블에서 composite primary key는 (회원명 + 책이름 + 날짜) 같군요.
근데 이 중에서 '책이름 컬럼'에만 종속되어있으니
제2정규형 테이블 만들고 싶으면 옮기는게 좋겠군요.
위 테이블에서 composite primary key는 (회원명 + 책이름 + 날짜) 같군요.
근데 이 중에서 '회원명 컬럼'에만 종속되어있으니
제2정규형 테이블 만들고 싶으면 옮기는게 좋겠군요.
composite primary key는 (회원명 + 책이름 + 날짜) 3개 중에
하나의 컬럼에만 달랑 종속되진 않습니다.
(회원명 + 책이름 + 날짜) 조합마다 종속되어야하기 때문에 옮길 필요는 없습니다.
그냥 빡통식으로 쉽게 생각하면 반납여부는 [책대여내역 table] 이라는 주제와 매우 관련있어서 옮기면 안됩니다.
제3정규형 (3rd normal form)
제2정규형을 만족하는 테이블에서 'primary key' 또는 'composite primary key' 컬럼에 종속된게 아닌
하찮은 잔챙이 컬럼에 종속된 컬럼을 다른 테이블로 빼면
그게 제3정규형 테이블
제2정규형에서 '이상구'의 출신대학이 바껴서 수정해야할 경우, 데이터가 적다면
작업이 어렵지 않겠지만 수정해야할 항목이 많은 경우 제3정규화 작업을 하여
원만한 db관리가 필요
제3정규형 - 어려운버전
제2정규형 테이블에서 transitive dependency도 제거해버리면 그게 제3정규형입니다.
transitive dependency는
composite primary key 또는 primary key 역할을 하는 컬럼이 있고
거기에 직접 종속된 컬럼A가 있고
또 거기에 직접 종속된 하찮은 컬럼B가 있으면
컬럼B가 primary key 컬럼에 transitive dependency 가 있다고 표현합니다.
그래서 그 컬럼B를 다른 테이블로 옮기라는 소리입니다.
옮기면 제3정규형을 만족하는 테이블이 완성됩니다.
primary key, foreign key 항상 넣으면 좋음
정규화하려고 테이블을 쪼갤 때가 많습니다. 그 경우 주의점은
다른 테이블에 있는 컬럼내용을 가져다쓸 때도 primary key를 사용하는게 좋습니다.
▲ 예를 들어서 아까처럼 제3정규화 하느라 이렇게 테이블을 분리해놨다고 칩시다.
이 테이블을 쓸만하게 고쳐보면
거기에 강사 이름이 들어가야하는데 강사 정보는 오른쪽 테이블에 들어있군요.
그럴 경우 강사 이름을 그대로 적는것 보다는 강사의 id를 적는게 좋습니다.
이러면 나중에 동명이인 강사가 생겨도 명확히 구분할 수 있으니까요.
저기서 강사id 컬럼을 전문용어로 foreign key 라고 합니다.
어려운건 아니고 다른 테이블에 있던 primary key를
다른 테이블에 사용할 때는 foreign key라고 부릅니다.
참고로 알아둡시다.
Foreign key 등록하는 법
foreign key가 등록된 모습
▲ 위 사진처럼 프로그램, 가격, 강사, 출신대학까지 이렇게 4개의 컬럼을
한 번에 출력하고 싶으면
SELECT *
FROM program, teacher
이상하게 출력됨...
위와 같은 원리로 (이중 for문과 비슷한듯?) 15줄이 출력됨
SELECT 프로그램, 가격, 강사, 출신대학
FROM program, teacher
WHERE program.강사id = teacher.id
SELECT 출력할컬럼들
FROM 테이블1 INNER JOIN 테이블2
ON 조건문
SELECT 프로그램, 가격, 강사, 출신대학
FROM program INNER JOIN teacher
ON program.강사id = teacher.id
테이블 3개 이상 합쳐서 출력하고 싶은 경우
SELECT *
FROM 테이블1, 테이블2, 테이블3
WHERE 조건1 AND 조건2 ...
SELECT *
FROM 테이블1
INNER JOIN 테이블2 ON 조건1
INNER JOIN 테이블3 ON 조건2
Q1.
sales 테이블을 출력하는데 위 사진처럼 product 테이블에 있던 상품명, 가격도 함께 출력해봅시다.
SELECT sales.id, 고객번호, 구매날짜, 상품명, 가격
FROM sales
INNER JOIN product
ON sales.상품id = product.id
Q2.
sales 테이블을 출력하는데 위 사진처럼 상품명, 가격, 고객명도 함께 출력해봅시다.
// 내가 짠 코드
SELECT sales.id, 고객번호, 구매날짜, 상품명, 가격, 고객명 FROM sales
INNER JOIN product
ON sales.상품id = product.id
INNER JOIN user_table
ON sales.고객번호 = user_table.id
ORDER BY sales.id ASC; // id순 오름차순 정렬
//선생님이 짠 코드
SELECT sales.id, 고객번호, 구매날짜, 상품명, 가격, 고객명
FROM sales
INNER JOIN product
ON sales.상품id = product.id
INNER JOIN user_table
ON sales.고객번호 = user_table.id
Q3.
날짜별 매출 합계를 출력하도록 2번에서 작성한 코드를 업그레이드 해봅시다.
SET sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));
SELECT sales.id, 고객번호, 구매날짜, 상품명, SUM(가격), 고객명 FROM sales
INNER JOIN product
ON sales.상품id = product.id
INNER JOIN user_table
ON sales.고객번호 = user_table.id
GROUP BY 구매날짜
ORDER BY 구매날짜 ASC; // 내가 짠 코드
SELECT sales.id, 고객번호, 구매날짜, 상품명, SUM(가격), 고객명
FROM sales
INNER JOIN product
ON sales.상품id = product.id
INNER JOIN user_table
ON sales.고객번호 = user_table.id
GROUP BY 구매날짜 // 선생님이 짠 코드
왼쪽 테이블 전체 + 공통된 행 출력하고 싶으면 LEFT JOIN
SELECT *
FROM program
LEFT JOIN teacher
ON program.강사id = teacher.id
오른쪽 테이블 전체 + 공통된 행 출력하고 싶으면 RIGHT JOIN
SELECT *
FROM program
RIGHT JOIN teacher
ON program.강사id = teacher.id
데이터 집어넣고 싶으면 INSERT
INSERT INTO 테이블명 (컬럼명1, 컬럼명2 ...) VALUES (값1, 값2 ...)
INSERT INTO product (id, 상품명, 가격) VALUES (1, '김치', 500)
INSERT INTO product (상품명, 가격) VALUES ('두부', 1000)
INSERT INTO product VALUES (3, '수박', 1500)
INSERT INTO product VALUES (4, '참외', 2000), (5, '배추', 2500); // 여러행 동시 삽입
모든 컬럼말고 일부 컬럼에만 데이터 저장할 수도 있다.
모든 컬럼에 빠짐없이 데이터를 넣는 경우 컬럼명은 생략할 수 있다.
다만 나중에 새로운 컬럼을 누가 만들거나 그러면 문제될 수 있으므로
컬럼명도 쓰는게 낫다.
다른 테이블에 있던 데이터 복사도 가능
INSERT INTO product SELECT 컬럼명 FROM 테이블명
INSERT INTO product (id, 상품명, 가격)
SELECT id, 상품명, 가격 FROM product2;
테이블 복사문법 2
CREATE TABLE 새로운테이블명 SELECT * FROM 기존테이블명
CREATE TEMPORARY TABLE 새로운테이블명 SELECT * FROM 기존테이블명
UPDATE / SET
UPDATE 테이블명
SET 컬럼1 = 값, 컬럼2 = 값
WHERE 조건식
UPDATE product
SET 가격 = 5000, 상품명 = '단무지'
WHERE id = 1;
UPDATE product
SET 가격 = 가격 + 100 // set 옆에 등호는 대입한다는 뜻
WHERE id = 1
삭제하려면 DELETE FROM
DELETE
FROM 테이블명
WHERE 조건식
응용 : JOIN & UPDATE
UPDATE A INNER JOIN B
ON 쪼인조건
SET 수정할내용
WHERE 조건식
응용 : JOIN & DELETE
DELETE A
FROM A INNER JOIN B
ON 쪼인조건
WHERE 조건식
UPDATE user_sales
SET email = IF(first_name = Solly, 'admin@test.com', 'test@test.com')
WHERE email = ''; // 공백
DELETE
FROM user_sales
WHERE sales IS NULL