# 예시 1
INSERT [INTO] 테이블이름[(열1,열2,,,)] VALUES (값1,값2,,,)
# 예시 2
USE cookDB;
CREATE TABLE testTBL1(id int, userName char(3), age int);
INSERT INTO testTBL1(1,'뽀로로',16);
# 예시 3
INSERT INTO testTBL1(id,userName) VALUES(2,'크롱');
# 예시 4
INSERT INTO testTBL1(userName, age, id) VALUES('루피',14,3);
CREATE TABLE testTBL2(
id int AUTO_INCREMENT PRIMARY KEY,
userName char(3),
age int
);
INSERT INTO testTBL2 VALUES (NULL,'에디',15);
INSERT INTO testTBL2 VALUES (NULL,'포비',12);
이런 경우도 가능해요.
- AUTO_INCREMENT 입력값을 100부터 시작하도록 변경
ALTER TABLE testTBL2 AUTO_INCREMENT=100; INSERT INTO testTBL2 VALUES(NULL,'에디',15); INSERT INTO testTBL2 VALUES(NULL,'통통이',12); SELECT * FROM testTBL2;
id userName age 100 에디 15 101 통통이 12
- AUTO_INCREMENT로 증가되는 값 지정
CREATE TABLE testTBL2( id int AUTO_INCREMENT PRIMARY KEY, userName char(3), age int ); ALTER TABLE testTBL2 AUTO_INCREMENT=100; SET @auto_increment_increment=3; INSERT INTO testTBL2 VALUES (NULL,'에디',15); INSERT INTO testTBL2 VALUES (NULL,'통통이',12); INSERT INTO testTBL2 VALUES (NULL,'크롱',12); SELECT * FROM testTBL2;
id userName age 100 에디 15 103 통통이 12 106 크롱 12 여기서 잠깐! 🖐
꿀팁🍯 : 데이터 삽입 시 코드를 줄이려면 여러 행 한꺼번에 입력 가능INSERT INTO testTBL2 VALUES (NULL,'에디',15), (NULL,'통통이',12), (NULL,'크롱',12); SELECT * FROM testTBL2;
- mysql은 auto commit(모든구문끝날때마다자동커밋)이므로 rollback은 안되는 경우가 기본
- 설정에 따라 commit 범위가 다 다름
INSERT INTO ,,, SELECT 문 사용하기
# employees 테이블의 데이터를 가져와 testTBL3 테이블에 입력
USE cookDB;
CREATE TABLE testTBL3(id int,Fname varchar(50),Lname varchar(50));
INSERT INTO testTBL3
SELECT emp_no,first_name,last_name FROM employees.employees;
# 아예 테이블 정의까지 생략
CREATE TABLE testTBL3
(SELECT emp_no,first_name,last_name FROM employees.employees);
SELECT * FROM testTBL3 LIMIT 3;
# 열이름 바꾸어 테이블 생성
CREATE TABLE testTBL3
(SELECT emp_no AS id,first_name AS Fname,last_name AS Lname FROM employees.employees);
SELECT * FROM testTBL3 LIMIT 3;
UPDATE 테이블이름
SET 열1=값1, 열2=값2, ,,,
WHERE 조건;
WHERE절을 생략할 순 있지만, 그렇게 되면 테이블 전체의 행이 수정됨
# Fname이 Kyoichi인 사람의 Lname을 없음으로 변경
USE cookDB;
UPDATE testTBL4
SET Lname='없음'
WHERE Fname='Kyoichi';
# 구매 테품 가경ㄱ 모두 현재 단가보다 1.5배 인상
UPDATE buyTBL
SET price=price*1.5;
DELETE FROM 테이블이름 WHERE 조건;
# Fname이 Aamer인 상위 5건 삭제
DELTE FROM testTBL4 WHERE Fname='Aamer' LIMIT 5;
예시를 통해 대용량 테이블 삭제
CREATE TABLE bigTBL1(SELECT * FROM employees.employees) DELETE FORM bitTBL1; DROP TABLE bitTBL2; TRUNCATE TABLE bitBL3;
결과를 보면 DELETE문만 실행시간이 오래 걸린다.
WHY??
- DML인 DELETE문은 트랜잭션 로그를 기록하는 작업을 하기 때문에 삭제하는 데 시간이 오래 걸림
- DDL인 DROP문은 테이블 자체를 삭제하고 트랜잭션 로그를 기록하지 않음
- DDL인 TRUNCATE문은 DELETE문과 결과 동일하지만 트랜잭션 로그를 기록하지 않음
- 대용량 테이블 삭제할 때, 큰 일을 작게 분할해서 사용하는 게 많음.
- delete 뒤에 limit 를 주면 주기적으로 많은 양을 삭제 가능
- 많은 양의 데이터를 삭제하는 것보다 신규테이블생성하고 과거테이블과 바꿔치기(우회,,해서 과거테이블 drop) 하는게 더 이득
- 갑자기 많은 것을 삭제하는것(한방쿼리)는 분할해서 작업하는 것이 더 현명
- drop은 되게 위험, truncate나 delete가 유용
INSERT INTO memberTBL VALUES ('KHD', '강후덜','미국');
INSERT IGNORE INTO memberTBL VALUES ('KHD', '강후덜','미국');
INSERT INTO memberTBL VALUES ('KHD','강후덜','미국') ON DUPLICATE KEY UPDATE userName='강후덜', addr="미국";
<순위함수이름>() OVER(
[PARTITION BY <partition_by_list>]
ORDER BY <order_by_list>)
"순위 함수 사용하기"예제를 통해 알아봅시다
1. cookDB초기화
2. 키가 큰 순, 키가 동일 시 이름 가나다순,으로 정렬USE cookDB; SELECT ROW_NUMBER() OVER(ORDER BY height DESC, userName ASC) "키큰순위", userName,addr,height FROM userTBL;
- 각 지역별로 순위 매기기
SELECT addr, ROW_NUMBER() OVER(PARTITION BY addr ORDER BY height DESC, userName ASC) "지역별 키큰순위", userName, height FROM userTBL;
- 키 동일 시 동일한 등수 처리
SELECT DENSE_RANK() OVER(ORDER BY height DESC) "키큰순위", addr, height FROM userTBL;
- 동일한 등수 시 그 다음 등수는 갯수대로 등수 매기기
SELECT RANK() OVER(ORDER BY height DESC) "키큰순위", userName, height FROM userTBL;
- 10명 사용자를 키 큰 순으로 정렬하고 2개 반으로 나누는 경우
SELECT NTILE(2) OVER(ORDER BY height DESC) "반번호", userName, addr, height FROM userTBL;
p 207 그림 6-23 참고
1. 샘플 테이블 만들기
2. 피벗 테이블 만들기
계절별로 판매 수량이 합산되게 함
SELECT uName,
SUM(CASE WHEN season='봄' THEN amout END) AS '봄'
SUM(CASE WHEN season='여름' THEN amout END) AS '여름'
SUM(CASE WHEN season='가을' THEN amout END) AS '가을'
SUM(CASE WHEN season='겨울' THEN amout END) AS '겨울'
FROM pivotTest
GROUP BY uName;
WITH CTE_테이블이름(열이름)
AS
(
<쿼리문>
)
SELECT 열이름 FROM CTE_테이블이름;
1. 구매 테이블에서 총구매액을 구하는 쿼리문 예제를 통해 알아봅시다
2. 회원 테이블에서 각 지역별로 가장 키가 큰 사람을 1명씩 뽑아 키의 평균을 구하는 예제를 통해 알아봅시다.
# AAA나 BBB 쿼리문에서는 CCC를 참조할 수 없음
AAA(칼럼들)
AS (AAA의 쿼리문),
BBB(칼럼들)
AS (BBB의 쿼리문),
CCC(칼럼들)
AS (CCC의 쿼리문)
- 가능하면 varchar를 사용 => 성능차이 많이 없음
- char를 많이 안씀 => 성능에는 유리하지만, 예외의 상황이 생겼을 때 비교하기 힘듦
<날짜와 시간 데이터 형식의 종류>
- DATE : 바이트 수 3
- TIME : 바이트 수 3
- DATETIME : 바이트 수 8
- TIMESTAMP : 바이트 수 4
- YEAR : 바이트 수 1
sql도 일반 프로그래밍 언어처럼 변수 선언하고 사용가능
SET @변수이름 = 변수값; SELECT @변수이름;
USE cookDB;
SET @myVar1=5;
SET @myVar2=3;
SET @myVar3=4.25;
SET @myVar4='MC 이름==> ';
SELET @myVar1;
SELET @myVar2+@myVar3;
SELET @myVar4, userName FROM userTBL WHERE height >180;
@myVar1 | @myVar2+@myVar3 | @myVar4 | userName |
---|---|---|---|
5 | 7.2500000000000000 | MC이름==> | 강호동 |
MC이름==> | 박수홍 |
SET @myVar1=3;
# 쿼리문을 준비만하고 실행하지 X
PREPARE myQuery
FROM 'SELECT userName, height FROM userTBL ORDER BY height LIMIT ?';
# EXECUTE쿼이름 구문을 만나는 순간 실행됨
# 'USING @ 변수' 의 변수가 'LIMIT ?' 의 물음표에 대입
EXECUTE myQuery USING @myVar1;
CAST(expression AS 데이터형식[(길이)])
CONVERT(expression, 데이터형식[(길이)])
예시를 통해 알아봅시다.
USE cookDB: SELECT AVG(amount) AS '평균 구매 개수' FROM buyTBL;
. 평균구매개수 . 2.9803 ❗️ 구매 개수는 실수가 아닌 정수여야 함❗️
SELECT CAST(AVG(amount) AS SIGNED INTEGER) AS '평균 구매 개수' FROM buyTBL; 또는 SELECT CONVERT(AVG(amount), SIGNED INTEGER) AS '평균 구매 개수' FROM buyTBL;
# 문자와 문자를 더함 => 정수로 변환후 처리
SELECT '100'+'200'; = 300
# CONCAT()은 문자열을 연결하는 함수이므로 문자열 그대로 처리
SELECT CONCAT('100','200'); = 100200
# CONCAT()함수안의 정수 100을 문자열로 변환 후 처리
SELECT CONCAT(100,'200'); = 100200
# 비교 연산으로 인해 3이 들어간 문자열이 숫자 3으로 변경돼 결국 '1>3'으로 처리 => 결과 거짓
SELECT 1 > '3mega'; = 0
# 위와 동일한 결과
SELECT 4 > '3MEGA'; = 0
# 앞에 'm'이 들어간 문자열이 숫자로 변경되며 그냥 0 이 돼서 결국 '0=0'으로 처리 => 결과 참
SELECT 0 = 'mega3'; = 1(참)
JSON데이터?
- 웹 환경이나 모바일 응용 프로그램 등에서 데이터를 교환하기 위해 만든 개방형 표준 포맷
- 속성(key)과 값(value)의 쌍
- javascript에서 파생됐지만 종속되지 않은 독립적인 데이터 포맷
예제를 통해 알아봅시다.
USE cookDB;
SELECT JSON_OBJECT('name', userName, 'height', height) AS 'JSON값'
FROM userTBL
WHERE height>=180;
. | JSON값 |
---|---|
. | {"name":"a","height":120} |
. | {"name":"b","height":180} |
. | {"name":"c","height":168} |
. | {"name":"d","height":190} |
SET @json='{"userTBL":
[
{"name":"a","height":120}
{"name":"b","height":180}
{"name":"c","height":168}
{"name":"d","height":190}
]
}';
# JSON_VALID() : 문자열이 JSON 형식을 만족하면 1, 아니면 0 반환 => 1
SELECT JSON_VALID(@json) AS JSON_VALID;
# JSON_SEARCH() : 세번째 파라미터에 주어진 문자열 위치 반환
# 'one' : 처음으로 매치되는 하나 반환 / 'all' : 매치되는 모든 것 반환
# 위치 : $.userTBL[2].name
SELECT JSON_SEARCH(@json, 'one', 'c') AS JSON_SEARCH;
# JSON_SEATCH()와 반대로 지정된 위치의 값 반환
# 값 : c
SELECT JSON_EXTRACT(@json, '$userTBL[2].name') AS JSON_EXTRACT;
# JSON_INSERT() : 새로운 값 추가
.
# JSON_REPLACE() : 값 변경
.
# JSON_REMOVE() : 지정된 항목 삭제
.
영화 한편의 대본(LONGTEXT 형식), 동영상 파일(LONGBLOB 형식) 를 사용하는 예제를 통해 알아봅시다.
1. 대용량 텍스트 파일과 동영상 준비
2. 영화 데이터베이스 만들기CREATE DATABASE moviDB; USE movieDB; CREATE TABLE movieTBL( movie_id INT, movie_title VARCHAR(30), movie_director VARCHAR(20), movie_star VARCHAR(20), movie_script LONGTEXT, movie_film LONGBLOB ) DEFAULT CHARSET=utf8mb4;
- 대용량 데이터 입력하기
INSERT INTO movieTBL VALUES(1, '쉰들러 리스트', '스필버그', '리암 니슨', LOAD_FILE('C:/SQL/Movies/SCHINDLER.txt'), LOAD_FILE('C:/SQL/Movies/SCHINDLER.mp4'));
❗️ 하지만 조회해보면 영화 대본과 영화 동영상이 NULL값으로 표시됨
💡 왜냐하면 아무것도 입력되지 않았기 때문이다.
❗️ 왜 아무것도 입력되지 않았나요?
💡 1. 최대 패킷 크기(최대 파일 크기)가 설정된 시스템 변수인 max_allowed_packet 값을 수정해주어야 함
💡 2. 파일을 업로드하거나 다운로드할 폴더 경로를 별도로 허용해주어야 함
4. 최대 파일 크기와 허용된 파일의 경로 추가하기# my.ini 파일 확인 CD %PROGRAMDATA% CD MySQL CD "MySQL Server 8.0" DIR # my.ini 열기 NOTEPAD my.ini # ctrl+f로 max_all 검색해서 max_allowed_packet 값 변경 max_allowed_packet=1024M # ctrl_f로 secure-file-priv 검색해서 아래에 한줄 추가하고 저장 secure-file-priv="C:/ProgramData/MySQL/MySQL Server 8.0/Uploads" secure-file-priv="C:/SQL/Movies" # my.ini 파일 변경해주었으니 서버 재시작 NET STOP MySQL NET START MySQL
- 다시 대용량 데이터 입력하기
성공!!
- 입력된 데이터를 파일로 내려받기
영화 아이디가 1인 쉰들러 리스트의 영화대본을 SCHINDLER_out.txt 파일로 내려받기SELECT movie_script FROM movieTBL WHERE movie_id=1 INTO OUTFILE 'C:/SQL/Movies/SCHINDLER_out.txt' # 아래 명령어 = 줄 바꿈 문자도 그대로 저장하기 위한 옵션 LINES TERMINATED BY '\\n';