- 여러 사람이 공유하여 사용할 목적으로 체계화해 통합, 관리하는 데이터의 집합체.
- DBMS: DB를 관리해주는 서비스
- RDB: 관계형 DB, 저장된 데이터 사이에 관계가 있다.
- SQL: DB에서 데이터를 정의, 조작, 제어하기 위해 사용하는 언어.
- DDL: 데이터 정의(Definition) 언어 (CREATE, ALTER, DROP)
- DML: 데이터 조작(Manipulation) 언어 (INSERT, UPDATE, DELETE, SELECT)
- DCL: 데이터 제어(Control) 언어 (GRANT, REVOKE, COMMIT, ROLLBACK)
- 데이터 사이언스의 경우 DML을 많이 사용하고 특히 SELECT가 중요.
- 터미널에서 시작
- mysql -u root -p
- mysql -u root -p
- SELECT 컬럼, AGG(컬럼)
- FROM 테이블
- WHERE 조건
- GROUP BY 컬럼
- (HAVING 조건)
- ORDER BY 컬럼
- DB 목록 확인
- show databases;
- DB 생성
- create database testdb;
- show databases;
- DB 사용
- use testdb;
- DB 삭제
- drop database testdb;
- show databases;
- user 조회
- use mysql;
- select host, user from user;
- user 생성
- 로컬
- create user 'username'@'localhost' identified by 'password';
- 여기서 username 이랑 password 알아서 수정
- select host, user from user;
- 외부
- create user 'username'@'%' identified by 'password';
- 여기서 username 이랑 password 알아서 수정
- select host, user from user;
- 로컬
- user 삭제
- drop user 'username'@'localhost';
- drop user 'username'@'localhost';
- 사전 작업
- create database testdb;
- use mysql;
- create user 'noma'@'localhost' identified by '1234';
- 모든 권한 목록 확인
- show grants for 'noma'@'localhost';
- 특정 DB의 모든 권한 부여
- grant all on testdb.* to 'noma'@'localhost';
- 안보일 때 새로고침
- flush privileges;
- 특정 DB의 모든 권한 삭제
- revoke all on testdb.* from 'noma'@'localhost';
- revoke all on testdb.* from 'noma'@'localhost';
- DB 안에서 데이터가 저장되는 형태. row와 column로 구성된 데이터 모음.
- 사전 설정
- create database zerobase default character set utf8mb4;
- 테이블 생성
- create table mytable(id int, name varchar(16));
- show tables;
- 테이블 정보 확인
- desc mytable;
- (컬럼 별로 디스크립션 출력)
- 테이블 이름 변경
- alter table mytable rename person;
- show tables;
- 컬럼 추가
- alter table person add column agee double;
- desc person;
- 컬럼 데이터 타입 수정
- alter table person modify column agee int;
- desc person;
- 컬럼 이름 수정
- alter table person change column agee age int;
- desc person;
- 컬럼 삭제
- alter table person drop column age;
- desc person;
- 테이블 삭제
- drop table person;
- show tables;
- 데이터 추가 명령어
- 입력한 컬럼 이름 순서와 값의 순서가 일치해야함.
- insert into 외우기
- 사전 설정
- use zerobase;
- create table person(id int, name varchar(16), age int, sex char);
- desc person;
- 데이터 추가
- insert into person (id, name, age, sex)
- values (1, '이효리', 43, 'F');
- select * from person;
- 모든 컬럼을 다 넣는다면 컬럼명 생략 가능
- insert into person values
- (2, '이상순', 48, 'M');
- select * from person;
- 데이터 조회 명령어
- select * from table 외우기
- 데이터 조회
- select name, age, sex from person;
- select * from person;
- 특정 조건에 만족하는 것 조회
- where 사용 조회
- select * from person where sex='F';
- select * from person where sex='F';
- 데이터 수정 명령어
- update table set 수정사항 외우기
- 데이터 수정
- update person set age=23 where name='이효리';
- select * from person where name='이효리';
- 데이터 삭제 명령어
- delete from 외우기
- 데이터 삭제
- delete from person where name='이상순';
- select * from person;
- 테이블 생성
- create table celeb
- ( ID int not null auto_increment primary key, NAME varchar(32) not null default '', BIRTHDAY date, AGE int, SEX char(1), JOB_TITLE varchar(32), AGENCY varchar(32) );
- desc celeb;
- 데이터 입력
- INSERT INTO celeb VALUES (1, '아이유', '1993-05-16', 29, 'F', '가수, 텔런트', 'EDAM엔터테이먼트'); INSERT INTO celeb VALUES (2, '이미주', '1994-09-23', 28, 'F', '가수', '울림엔터테이먼트'); INSERT INTO celeb VALUES (3, '송강', '1994-04-23', 28, 'M', '텔런트', '나무엑터스'); INSERT INTO celeb VALUES (4, '강동원', '1981-01-18', 41, 'M', '영화배우, 텔런트', 'YG엔터테이먼트') ; INSERT INTO celeb VALUES (5, '유재석', '1972-08-14', 50, 'M', 'MC, 개그맨', '안테나'); INSERT INTO celeb VALUES (6, '차승원', '1970-06-07', 48, 'M', '영화배우, 모델', 'YG엔터테이먼트'); INSERT INTO celeb VALUES (7, '이수현', '1999-05-04', 23, 'F', '가수', 'YG엔터테이먼트');
- select * from celeb;
- select 문에서 특정 컬럼을 기준으로 정렬
- ASC(ascending)은 오름차순 정렬
- DESC(descending)은 내림차순 정렬
- 기본 값은 ASC 오름차순
- 정렬해서 가져오기
- select age, name from celeb order by age asc;
- select age, name from celeb order by age desc;
- select age, name from celeb order by age, name;
- select age, name from celeb order by age desc, name asc;
- 비교 연산자
- 같다(=), 같지 않다(<>, !=)
- 초과 미만(>), 이상 이하(>=)
- 비교 연산자 사용
- select name, age from celeb where age=29 order by age;
- select name, age from celeb where age!=29 order by age;
- select name, age from celeb where age<>29 order by age;
- select name, age from celeb where age>29 order by age;
- select name, age from celeb where age<29 order by age;
- select name, age from celeb where age>=29 order by age;
- select name, age from celeb where age<=29 order by age;
- 논리 연산자
- 결과를 bool로 리턴
- AND, OR
- NOT: 조건 만족하지 않을때 TRUE
- BETWEEN: 조건값이 범위 사이에 있을때 TRUE
- IN: 조건값이 목록에 있으면 TRUE
- LIKE: 조건값이 패턴에 맞으면 TRUE
- AND가 OR보다 먼저 적용
- 괄호 사용하면 우선순위 수정 가능
- AND, OR 사용
- select * from celeb where age=29 and sex='F';
- select * from celeb where sex='M' and age>40 order by name desc;
- select * from celeb where age<25 or age>30 order by age;
- select * from celeb where (age<29 and sex='F') or (age>30 and sex='M') order by age, sex;
- select * from celeb where (agency='YG엔터테이먼트' or agency='나무엑터스') and age<30;
- NOT 사용
- select * from celeb where not sex='F';
- select * from celeb where (agency='YG엔터테이먼트' and not sex='M') or (job_title='가수' and not agency='YG엔터테이먼트');
- select * from celeb where (birthday>19901231 and not sex='F') or (birthday<19800101 and not agency='안테나');
- BETWEEN 사용
- select * from celeb where age between 20 and 40;
- 범위는 이상, 이하로 해당 숫자 포함이며, and로 대체 가능
- select * from celeb where age>=20 and age<=40;
- not 같이 사용하려면 between 앞에 적은 컬럼보다 앞에 not
- select * from celeb where (not birthday between 19800101 and 19951231 and sex='F') or (agency='YG엔터테이먼트' and not age between 20 and 45);
- IN 사용
- select * from celeb where age in (28, 48);
- or로 대체 가능
- select * from celeb where age=28 or age=48;
- select * from celeb where not agency in ('나무액터스', '안테나', '울림엔터테이먼트') and (sex='F' or age>=45);
- LIKE 사용
- select * from celeb where agency like 'YG엔터테이먼트';
- =로 대체 가능
- select * from celeb where agency='YG엔터테이먼트';
- 퍼센트 (%)
- 원하는 부분이 일치하는 데이터
- select * from celeb where agency like 'YG%';
- select * from celeb where agency like '%엔터테이먼트';
- select * from celeb where job_title like '%가수%';
- 언더바 (_)
- 두번째 글자가 G 인 데이터
- select * from celeb where agency like '_G%';
- 가 로 시작하고 최소 2글자 이상인 데이터
- select * from celeb where job_title like '가_%';
- 영 으로 시작하고 모델로 끝나는 데이터
- select * from celeb where job_title like '영%모델';
- 영화배우, 텔런트 병행 데이터
- select * from celeb where job_title like '%영화배우%' and job_title like '%텔런트%';
- 직업이 하나 이상, 영화배우 혹은 텔런트가 아닌 데이터
- select * from celeb where job_title like '%,%' and not (job_title like '%영화배우%' or job_title like '%텔런트%');
- 여러개 SQL문을 합쳐서 하나의 SQL문으로 만들기
- 컬럼의 개수가 반드시 같아야 한다.
- 컬럼의 종류가 달라도 괜찮은데 개수는 같아야 한다.
- UNION: 중복된 값을 제거하여 리턴
- UNION ALL: 중복된 값도 모두 리턴
- 실습환경 구축
- create table test1 (no int);
- create table test2 (no int);
- insert into test1 values (1);
- insert into test1 values (2);
- insert into test1 values (3);
- insert into test2 values (5);
- insert into test2 values (6);
- insert into test2 values (3);
- UNION 사용
- select * from test1 union all select * from test2;
- select * from test1 union select * from test2;
- select * from celeb where sex='F' union all select * from celeb where agency ='YG엔터테이먼트';
- select * from celeb where sex='F' union select * from celeb where agency ='YG엔터테이먼트';
- 두개 이상의 테이블을 결합하는 것
- table1 join table2 on 조건 외우기
- 만약에 컬럼 명이 같으면 on 대신 using 사용 가능 (비추)
- INNER JOIN: 교집합
- LEFT JOIN: 왼쪽 + 교집합
- RIGHT JOIN: 교집합 + 오른쪽
- FULL OUTER JOIN: 합집합
- SELF JOIN: 결과는 이너 조인이랑 동일
- LEFT와 RIGHT 특징
- 교집합이 아닌 데이터는 NULL로 채워서 나옴
- 레프트는 왼쪽이 먼저 표시, 교집합이 이어서 표시
- 라이트는 교집합이 먼저 표시, 오른쪽이 이어서 표시
- FULL OUTER JOIN 특징
- mysql에서는 사용 불가
- 순서는 왼쪽 먼저 표시, 교집합 이어서 표시, 오른쪽 이어서 표시
- 실습환경 구축
- create table snl_show (ID int not null auto_increment primary key, SEASON int not null, EPISODE int not null, BROADCAST_DATE date, HOST varchar(32) not null);
- desc snl_show;
- INSERT INTO snl_show VALUES (1, 8, 7, '2020-09-05', '강동원'); INSERT INTO snl_show VALUES (2, 8, 8, '2020-09-12', '유재석'); INSERT INTO snl_show VALUES (3, 8, 9, '2020-09-19', '차승원') ; INSERT INTO snl_show VALUES (4, 8, 10, '2020-09-26', '이수현'); INSERT INTO snl_show VALUES (5, 9, 1, '2021-09-04', '이병헌') ; INSERT INTO snL_show VALUES (6, 9, 2, '2021-09-11', '하지원') ; INSERT INTO snl_show VALUES (7, 9, 3, '2021-09-18', '제시'); INSERT INTO snl_show VALUES (8, 9, 4, '2021-09-25', '조정석'); INSERT INTO snl_show VALUES (9, 9, 5, '2021-10-02', '조여정') ; INSERT INTO snl_show VALUES (10, 9, 6, '2021-10-09', '옥주현');
- select * from snl_show;
- JOIN 사용
- select celeb.id, celeb.name, snl_show.id, snl_show.host from celeb inner join snl_show on celeb.name=snl_show.host;
- select celeb.id, celeb.name, snl_show.id, snl_show.host from celeb left join snl_show on celeb.name=snl_show.host;
- select celeb.id, celeb.name, snl_show.id, snl_show.host from celeb right join snl_show on celeb.name=snl_show.host;
- select celeb.id, celeb.name, snl_show.id, snl_show.host from celeb left join snl_show on celeb.name=snl_show.host union select celeb.id, celeb.name, snl_show.id, snl_show.host from celeb right join snl_show on celeb.name=snl_show.host;
- SELF JOIN 사용
- 쿼리에서는 생략 가능. 알아서 돌아간다.
- from 뒤에 테이블을 2개 다 적어야 한다.
- select celeb.id, celeb.name, snl_show.id, snl_show.host from celeb, snl_show where celeb.name=snl_show.host;
- select celeb.name, celeb.job_title from celeb, snl_show where celeb.name=snl_show.host and celeb.agency='안테나';
- select celeb.name, celeb.age, celeb.job_title, snl_show.season, snl_show.episode from celeb, snl_show where celeb.name=snl_show.host and ((not celeb.job_title like '%영화배우%' and celeb.agency='YG엔터테이먼트') or (celeb.age>=40 and agency!='YG엔터테이먼트'));
- select snl_show.id, snl_show.season, snl_show.episode, celeb.name, celeb.job_title from snl_show, celeb where snl_show.host=celeb.name;
- select snl_show.host from snl_show, celeb where snl_show.host=celeb.name and (snl_show.episode in (7, 9, 10) or celeb.agency like 'YG______') and broadcast_date>='20200915';
- 여러 문자열을 하나로 합치거나 연결
- CONCAT 사용
- select concat('concat', ' ', 'test')
- select concat('이름:', name) from celeb;
- 컬럼이나 테이블 이름에 별칭 생성
- as라고 사용하면 되는데 생략도 가능
- ALIAS 사용
- select name as '이름' from celeb;
- select name as '이름', agency as '소속사' from celeb;
- select concat(name, ': ', job_title) as profile from celeb;
- select s.season, s.episode, c.name, c.job_title from celeb as c, snl_show as s where c.name=s.host;
- select concat(s.season, '-', s.episode, '(', s.broadcast_date, ')') as '방송정보', concat (c.name, '(', c.job_title, ')') as '출연자정보' from celeb as c, snl_show as s where c.name=s.host;
- select concat(s.season, '-', s.episode, '(', s.broadcast_date, ')') as '방송정보', concat (c.name, '(', c.job_title, ')') as '출연자정보' from celeb c, snl_show s where c.name=s.host;
- 검색한 결과의 중복 제거
- select 바로 뒤에 넣기
- DISTINCT 사용
- select distinct agency from celeb;
- select sex, job_title from celeb where job_title like '%가수%';
- select distinct sex, job_title from celeb where job_title like '%가수%';
- 보통 COUNT랑 같이 사용
- 중복 없는 갯수
- select count(distinct agency) from celeb;
- 검색결과를 정렬된 순으로 주어진 숫자만큼의 행만 조회
- 가장 마지막에 적어서 사용
- LIMIT 사용
- select * from celeb limit 3;
- select * from celeb order by age limit 4;
- Amazon Web Service, Relational Database Service
- 클라우드 상에 데이터베이스를 구축
- 회원가입
- AWS 들어가서 회원가입
- 개인으로 선택
- 리전은 대한민국 선택
- 서포트 플랜 선택 (무료 버전)
- MySQL RDS 생성
- AWS 관리 콘솔 -> 왼쪽 상단 서비스 선택
- 데이터베이스 - RDS 클릭
- 데이터베이스 생성 누르기
- 표준 생성 선택
- MySQL 선택
- 템플릿은 프리티어로 선택
- DB 인스턴스 식별자는 그대로 사용
- 마스터 사용자 이름 입력 (예시, root)
- 마스터 암호 입력 (예시, root)
- 프리티어로 사용 가능한 클래스 선택
- 버스터블 클래스(t 클래스 포함) 선택
- 스토리지 SSD로 선택
- 스토리지 자동 조정은 반드시 비활성화
- 나머지는 기본으로 선택
- 연결 설정은 모두 기본값, 퍼블릭 액세스는 예 선택
- 퍼블릭 액세스 가능은 외부에서 연결 가능하도록 하는 것
- 보안 그룹, 포트 모두 기본
- 데이터베이스 인증은 암호 인증 (test 위한 것. 주의.)
- 추가구성 모두 기본값, 백업은 자동 백업 비활성화 선택
- 모니터링 비활성화
- 유지관리 모두 기본값, 삭제 방지는 활성화
- 데이터베이스 생성
- 상태가 사용 가능이 되면 생성 완료
- AWS RDS 외부 접속
- AWS 관리 콘솔 -> 왼쪽 상단 서비스 선택
- 데이터베이스 - RDS 클릭
- Amazon RDS의 데이터베이스 클릭
- 생성된 데이터베이스 클릭
- 연결 및 보안
- VPC 보안 그룹 클릭
- 보안 그룹 ID 클릭
- 인바운드 규칙 편집
- 규칙 추가
- MySQL/Aurora 선택, AnywhereIPv4 선택
- 규칙 저장 클릭
- 외부 접근 권한 발급 완료
- AWS RDS 접속
- AWS 관리 콘솔 -> 왼쪽 상단 서비스 선택
- 데이터베이스 - RDS 클릭
- Amazon RDS의 데이터베이스 클릭
- 생성된 데이터베이스 클릭
- 연결 및 보안
- 엔드포인트, 포트 복사 해놓기
- (터미널)
- mysql -h <엔드포인트> -P <포트> -u <마스터 사용자 이름> -p
- 마스터 암호 입력
- show databases;
- use mysql
- select host, user from user;
- AWS RDS 중지
- AWS 관리 콘솔 -> 왼쪽 상단 서비스 선택
- 데이터베이스 - RDS 클릭
- Amazon RDS의 데이터베이스 클릭
- 중지하려는 데이터베이스 목록 체크
- 작업 버튼 -> 중지 클릭
- 스냅샷 아니오, 중지합니다 클릭
- 시간이 많이 걸림
- 7일 중지되고 자동으로 다시 시작되니 주의
- AWS RDS 시작
- AWS 관리 콘솔 -> 왼쪽 상단 서비스 선택
- 데이터베이스 - RDS 클릭
- Amazon RDS의 데이터베이스 클릭
- 시작하려는 데이터베이스 클릭
- 오른쪽 상단에 작업 -> 시작 클릭
- 시간이 많이 걸림
- sql 확장자
- SQL 쿼리를 모아놓은 파일
- 쿼리를 한번에 실행시킬 수 있음
- 실습 환경
- 깃허브-로컬 레포지토리 하나 파기
- vscode로 해당 폴더 실행
- test01.sql 파일 하나 생성
- mysql 안에서 실행
- source </path/filename.sql>
- source 대신
\.
사용 가능 - 경로가 같다면 <filename.sql>만 쓰기 가능
- 실행 해보기
- mysql -u root -p zerobase (데이터베이스로 바로 접속)
- source test01.sql
- desc police_station;
- mysql 밖에서 실행
- 괄호 여는 꺾새(<) 사용
- mysql -u root -p zerobase < test02.sql
- desc crime_status;
- mysqldump 명령어
- 괄호 닫는 꺾새(>) 사용
- 백업 완료되면 파일이 하나 생성 된다.
- 백업한 파일을 실행하면 그 시점으로 복구 가능
- 백업 해보기
- mysqldump -u root -p zerobase > zerobase.sql
- 이걸 source로 사용 가능
- AWS RDS 서비스에서 백업
- AWS 관리 콘솔 -> 왼쪽 상단 서비스 선택
- 데이터베이스 - RDS 클릭
- Amazon RDS의 데이터베이스 클릭
- 데이터베이스 중지라면 시작으로 만들기
- 연결 및 보안에서 엔드포인트, 포트 확인
- mysql -h <엔드포인트> -P <포트> -u <마스터 사용자 이름> -p
- 마스터 암호 입력
- show databases;
- use zerobase;
- source zerobase.sql
- show tables;
- mysqldump 명령어
- 백업 해보기
- mysqldump -u root -p zerobase celeb > celeb.sql
- 이걸 source로 사용 가능
- 데이터 없이 테이블 생성 쿼리만 백업 가능
- mysqldump 뒤에 -d 넣어서 사용
- 백업 해보기
- mysqldump -d -u root -p zerobase snl_show > snl.sql
- mysqldump -d -u root -p zerobase snl_show > snl.sql
- !pip install mysql-connector-python
- import mysql.connector 확인
- 접속 많으면 안되니 그때 그때 종료하기
- 파이썬에서 mysql 접속
- mydb = mysql.connector.connect( host = 'localhost', user = 'root', password = 'root' )
- mydb.close()
- 데이터베이스 지정해서 접속
- mydb = mysql.connector.connect( host = 'localhost', user = 'root', password = 'root', database = 'zerobase', )
- mydb.close()
- 테이블 생성
- excute 안에 똑같이 쿼리 치기
- mydb = mysql.connector.connect( host = 'localhost', user = 'root', password = 'root', database = 'zerobase', )
- cur = mydb.cursor()
- cur.execute('create table sql_file (id int, filename varchar(16))')
- mydb.close()
- 터미널 mysql 접속
- desc sql_file;
- 테이블 삭제
- excute 안에 똑같이 쿼리 치기
- mydb = mysql.connector.connect( host = 'localhost', user = 'root', password = 'root', database = 'zerobase', )
- cur = mydb.cursor()
- cur.execute('drop table sql_file')
- mydb.close()
- 터미널 mysql 접속
- desc sql_file;
- sql 파일 실행
- 실행은 open().read() 함수 사용
- mydb = mysql.connector.connect( host = 'localhost', user = 'root', password = 'root', database = 'zerobase', )
- cur = mydb.cursor()
- sql = open('test03.sql').read()
- cur.execute(sql)
- mydb.close()
- 터미널 mysql 접속
- desc sql_file;
- sql 파일에 쿼리가 많은 경우 실행법
- multi=True로 변경
- for문 돌리면서 패치 만들고 커밋
- mydb = mysql.connector.connect( host = 'localhost', user = 'root', password = 'root', database = 'zerobase', )
- cur = mydb.cursor()
- sql = open('test04.sql').read()
- for i in cur.execute(sql, multi=True): if i.with_rows: print(i.fetchall()) else: print(i.statement)
- mydb.commit()
- mydb.close()
- 터미널 mysql 접속
- desc sql_file;
- 데이터를 가져온 경우에는 변수에 데이터를 담을 수 있음.
- 결과값을 변수에 모두 담을 때 사용
- fetch all 사용
- cur = mydb.cursor(buffered=True)
- cur.execute('select * from sql_file')
- result = cur.fetchall()
- 프린트 해보기
- 판다스로 읽기
- df = pd.DataFrame(result)
- df.head()
- csv 파일 데이터를 파이썬을 활용해 insert
- police_station.csv 파일 읽기
- df = pd.read_csv('police_station.csv')
- df.read()
- 파이썬 활용해 insert
- sql = 'insert into police_station values (%s, %s)'
- print('### INSERT ###')
- for i, row in df.iterrows(): cur.execute(sql, tuple(row)) print(tuple(row)) mydb.commit()
- 한글이 깨지는 경우
- pd.read_csv() 파라미터에 encoding='euc-kr' 추가
- pd.read_csv() 파라미터에 encoding='euc-kr' 추가
- 기본 키
- 테이블의 각 레코드를 식별
- 중복 없는 고유값 포함
- NULL 불가능
- 테이블 당 하나의 기본키를 가짐
- 컬럼 하나를 PRIMARY KEY로 지정 가능
- 여러 컬럼을 하나의 PRIMARY KEY로 지정 가능
- 한개의 컬럼을 설정
- 마지막 줄에 무엇을 키로 할건지 선언
- create table persons (pid int not null, name varchar(16), age int, sex char, primary key (pid));
- desc persons;
- 키값에 PRI라고 적혀 있는 것이 PRIMARY KEY
- 여러개의 컬럼을 설정
- 마지막 줄에 키를 2개 선언
- create table animal (name varchar(16) not null, type varchar(16) not null, age int, primary key (name, type));
- desc animal;
- PRIMARY KEY 삭제
- alter drop을 사용
- alter table persons drop primary key;
- desc persons;
- alter table animal drop primary key;
- desc animal;
- 이미 생성된 테이블에 PRIMARY KEY 설정
- alter add를 사용
- alter table persons add primary key (pid);
- desc persons;
- alter table animal add primary key (name, type);
- desc animal;
- CONSTRAINT 문법으로 설정
- alter table animal add constraint PK_animal Key (name, type);
- desc animal;
- 외래 키
- 테이블과 다른 테이블을 연결
- FOREIGN KEY로 지정된 컬럼은 연결할 테이블의 기본키가 된다.
- 지금 테이블의 PRIMARY KEY는 따로 있다.
- 다른 테이블의 PRIMARY KEY를 참조해서 FOREIGN KEY 컬럼을 만드는 것이다.
- 한 테이블에 2개 있을 수도 있다.
- CONSTRAINT 문법으로 FOREIGN KEY 설정
- create table orders (oid int not null, order_no varchar(16), pid int, primary key (oid), constraint FK_persons foreign key (pid) references persons(pid));
- desc orders;
- 키에 MUL 표시가 생김
- CONSTRAINT 생략하고 FOREIGN KEY 설정
- create table job (jid int not null, name varchar(16), pid int, primary key (jid), foreign key (pid) references persons(pid));
- FOREIGN KEY 삭제
- alter drop을 사용
- alter table orders drop foreign key FK_persons;
- 삭제 하더라도 키에 MUL 표시는 그대로 있다.
- 레퍼런스 관계만 깨지는 것
- show create table orders; 에서 확인 가능
- 생성된 테이블에 FOREIGN KEY 설정
- alter table orders add foreign key (pid) references persons(pid);
- desc orders;
- show create table orders;
- 추가 예제
- select count(distinct name) from police_station;
- select count(distinct police_station) from crime_status;
- select distinct name from police_station limit 3;
- select distinct police_station from crime_status limit 3;
- select c.police_station, p.name from crime_status c, police_station p where p.name like concat('서울', c.police_station, '경찰서') group by c.police_station, p.name;
- alter table police_station add primary key (name);
- desc police_station;
- alter table crime_status add column reference varchar(16);
- alter table crime_status add foreign key (reference) references police_station(name);
- update crime_status c, police_station p set c.reference=p.name where p.name like concat('서울', c.police_station, '경찰서');
- select distinct police_station, reference from crime_status;
- 이제 두 테이블은 연결되었다.
- crime_status가 police_station을 참조한다.
- 두 테이블을 조인할 때에는 FOREIGN KEY 기준으로 하면 된다.
- select c.police_station, p.address from crime_status c, police_station p where c.reference=p.name group by c.police_station;
- 여러 컬럼 혹은 전체 컬럼으로부터 하나의 결과값을 반환하는 함수
- COUNT: 총 갯수를 계산
- SUM: 합계를 계산
- AVG: 평균을 계산
- MIN: 최소값을 찾아 리턴
- MAX: 최대값을 찾아 리턴
- FIRST: 첫번째 값을 리턴
- LAST: 마지막 값을 리턴
- 명령어 뒤에 괄호를 붙여서 컬럼을 지정한다.
- 총 갯수를 계산
- select count(*) from police_station;
- 중복 제거한 결과 계산
- DISTINCT 사용
- select count(distinct police_station) from crime_status;
- select count(distinct crime_type) from crime_status;
- 숫자 컬럼의 합계를 계산
- select sum(case_number) from crime_status where status_type='발생';
- raw data를 확인하고 싶으면 집계함수만 빼고 검색하면 된다.
- select case_number from crime_status where status_type='발생';
- 숫자 컬럼의 평균을 계산
- select avg(case_number) from crime_status where crime_type like '폭력' and status_type='검거';
- select avg(case_number) from crime_status where police_station like '중부' and status_type='발생';
- 최소값을 찾아 리턴
- select min(case_number) from crime_status where crime_type like '강도' and status_type='발생';
- select min(case_number) from crime_status where police_station like '중부' and status_type='검거';
- 최대값을 찾아 리턴
- select max(case_number) from crime_status where crime_type like '살인' and status_type='검거';
- select max(case_number) from crime_status where police_station like '강남' and status_type='발생';
- 그룹화하여 데이터를 조회
- 집계함수를 활용하여 함께 사용하는 편
- ORDER BY와 함께 쓸 때는 GROUP BY를 먼저 쓴다.
- 그룹화 조회
- select police_station from crime_status group by police_station order by police_station limit 5;
- DISTICT를 사용하면 ORDER BY는 사용 불가
- select distinct police_station from crime_status limit 5;
- SUM과 같이 사용
- 경찰서 별로 범죄 발생 수 합
- select police_station, sum(case_number) 발생건수 from crime_status where status_type like '발생' group by police_station order by 발생건수 desc;
- AVG와 같이 사용
- 경찰서 별로 범죄 검거 수 평균
- select police_station, avg(case_number) 평균검거건수 from crime_status where status_type like '검거' group by police_station order by 평균검거건수 desc;
- 다른 종류 행 2개 출력
- (정보: status_type는 2개 뿐)
- select police_station, status_type, avg(case_number) from crime_status group by police_station, status_type;
- 집계함수의 조건문
- 조건에 집계함수를 쓰면 WHERE 대신 HAVING 사용
- 집계함수로 만든 값을 WHERE에서 쓰면 인식을 못한다.
- SELECT 가 더 늦게 실행되기 때문이다.
- SUM과 함께 사용
- select police_station, sum(case_number) cnt from crime_status where status_type like '발생' group by police_station having cnt > 4000;
- AVG와 함께 사용
- select police_station, avg(case_number) cnt from crime_status where (crime_type like '폭력' or crime_type like '절도') and status_type like '발생' group by police_station having cnt >= 2000;
- select police_station, avg(case_number) cnt from crime_status where (crime_type like '폭력' or crime_type like '절도') and status_type like '발생' group by police_station having cnt >= 2000;
- 입력값을 기준으로 단일 값을 반환
- UCASE: 영문을 대문자로 변환
- LCASE: 영문을 소문자로 변환
- MID: 문자열 일부분을 반환
- LENGTH: 문자열의 길이를 반환
- ROUND: 지정한 자리에서 숫자를 반올림
- NOW: 현재 날짜 및 시간을 반환
- FORMAT: 숫자를 천단위 콤마가 있는 형식으로 변환
- 영문을 대문자로, 소문자로 변환
- 예제
- select ucase(menu), price from sandwich where price > 15;
- select lcase(menu), price from sandwich where price < 5;
- 문자열 일부분을 반환
- MID(문자, A번, B개)으로 사용
- A번 위치부터 B개를 가져온다.
- 예제
- select mid('This is mid test', 1, 4);
- select mid('This is mid test', 6, 5);
- select mid('This is mid test', -4, 4);
- select mid('This is mid test', -8, 3);
- select mid(cafe, 6, 4) from sandwich where ranking = 11;
- select mid(cafe, -4, 4) from sandwich where ranking = 11;
- 문자열의 길이를 반환
- 예제
- select length('This is len test');
- select length('');
- select length(' ');
- select length(null);
- select length(address), address from sandwich where ranking<=3;
- 지정한 자리에서 숫자를 반올림
- ROUND(숫자, 반올림 위치)로 사용
- 반올림 위치 비워두면 0에서 반올림
- 예제
- select round(315.625);
- select round(315.625, 0);
- select round(315.625, 1);
- select round(315.625, -1);
- select ranking, price, round(price) from sandwich order by ranking desc limit 3;
- 현재 날짜 및 시간을 반환
- 예제
- select now();
- select now();
- 숫자를 천단위 콤마가 있는 형식으로 변환
- FORMAT(숫자, 표시할 소수점 위치)로 사용
- ROUND에 천단위 콤마 기능까지 더한 함수
- ROUND는 숫자를 리턴하지만 FORMAT은 스트링을 리턴하니 주의
- 예제
- select format(12345.6789, 0);
- select format(12345.6789, 2);
- select format(12345.6789, 10);
- select format(price, 0) from sandwich where round(price, 1)>=2;
- 하나의 SQL문 안에 포함되어 있는 또 다른 SQL문
- 큰 SQL문을 메인쿼리, 포함된 SQL문을 서브쿼리라고 한다.
- 괄호로 묶어서 사용
- 단일 행 혹은 복수 행 비교 연산자와 함께 사용 가능
- 서브쿼리에서는 ORDER BY 사용 불가
- 메인쿼리가 서브쿼리를 포함하는 종속적인 관계
- 서브쿼리는 메인쿼리의 컬럼 사용 가능
- 메인쿼리는 서브쿼리의 컬럼 사용 불가
- 종류
- 스칼라 서브쿼리: SELECT 절에 사용
- 인라인 뷰: FROM 절에 사용
- 중첩(nested) 서브쿼리: WHERE 절에 사용
- SELECT 절에 사용
- 결과는 하나의 컬럼만 반환하게 해야한다.
- SELECT 절에는 원래 컬럼이 온다.
- 컬럼 한개 대신 이 스칼라 서브쿼리를 사용하는 것
- 예제
- select case_number, (select avg(case_number) from crime_status where crime_type like '강도' and status_type like '검거') avg from crime_status where police_station like '은평' and crime_type like '강도' and status_type like '검거';
- select case_number, (select avg(case_number) from crime_status where crime_type like '강도' and status_type like '검거') avg from crime_status where police_station like '은평' and crime_type like '강도' and status_type like '검거';
- FROM 절에 사용
- FROM 절에는 원래 테이블이 온다.
- 인라인 뷰 서브쿼리가 실행된 결과를 테이블로 사용하는 것
- 예제
- select c.police_station, c.crime_type, c.case_number from crime_status c, (select police_station, max(case_number) cnt from crime_status where status_type like '발생' group by police_station) m where c.police_station=m.police_station and c.case_number=m.cnt;
- select c.police_station, c.crime_type, c.case_number from crime_status c, (select police_station, max(case_number) cnt from crime_status where status_type like '발생' group by police_station) m where c.police_station=m.police_station and c.case_number=m.cnt;
- WHERE 절에 사용
- 중첩 서브쿼리 종류
- single row: 하나의 결과값을 검색
- multiple row: 하나 이상의 결과값을 검색
- multiple column: 하나 이상의 컬럼을 검색
- single row 예제
- 대부분 비교연산자와 사용할 때 결과값이 하나여야 한다.
- 이럴 때 single row 사용
- 따로 문법이 있는건 아니고 조건문으로 1개로 제한하기
- select name from celeb where name=(select host from snl_show where id=1);
- multiple row 예제
- IN과 사용할 때 결과값은 여러개 가능
- 이럴 때 multiple row 사용
- select host from snl_show where host in (select name from celeb where job_title like '%영화배우%');
- EXISTS와 사용하는 경우
- select name from police_station p where exists (select police_station from crime_status c where p.name=c.reference and case_number>2000);
- ANY와 사용하는 경우
- select name from celeb where name=any (select host from snl_show);
- ALL과 사용하는 경우
- select name from celeb where name=all (select host from snl_show where id=1);
- multiple column 예제
- WHERE 절에서 컬럼과 컬럼들을 IN과 사용할 때 사용
- select name, sex, agency from celeb where (sex, agency) in (select sex, agency from celeb where name='강동원');
- 테이블 불러올 때는 ESC 밑에 백틱 사용
- 스트링 사용할 때는 엔터 옆에 따옴표 사용
- 완성된 쿼리문 서브쿼리로 사용
- with 절이 조인도 가능하고 더 좋다.
- 하지만 메모리를 많이 사용하므로 주의한다.
- with 절
- 쿼리문을 with tb as () 로 감싼다.
- 다음 쿼리에서 테이블을 불러오듯 from에서 tb를 사용하면 된다.
- from 절
- from 뒤 테이블 위치에 ()로 감싸 넣어준다.
- where 조건절은 주석처리 쉽게 True먼저 걸고 and로 묶는다.
- where True and col1 is not null and col2 is not null
- select 에서도 주석처리 쉽게 마지막 값도 ,를 붙여준다.
- 조건에 따라 값 부여하기
- 조건 대상 1개 컬럼
- case (col1) when (조건1) then (조건1 해당할 때 결과) when (조건2) then (조건2 해당할 때 결과) else (모두 해당하지 않을 때 결과) end as level
- 조건 대상 여러개 컬럼
- case when (col1 조건1) then (조건1 해당할 때 결과) when (col2 조건2) then (조건2 해당할 때 결과) else (모두 해당하지 않을 때 결과) end as level
- 조건 대상 1개 컬럼
- window 함수 집계
- 집계함수를 window 함수로 사용할 수 있다.
- 집계된 결과값을 기존 데이터에 컬럼을 추가해 보여준다.
- 결과를 보여줄 때 행 수가 줄어들지 않는 특징이 있다.
- group by는 집계 결과만 보여주므로 행 수 가 줄어든다.
- over, partition by 와 함께 사용된다.
- select sum(col1) over (partition by col2) from table
- window 함수 컬럼 순서변경
- lead: 2행 값이 1행으로 온다. 뒤에 있던 값이 리더로 앞서간다.
- lag: 1행 값이 2행으로 간다. 앞에 있던 값이 질질 끌려 뒤로간다.
- order by 와 함께 사용된다.
- division by 0 에러
- 분모를 0으로 나눈 경우에 발생한다.
- 분모를 0 대신에 NULL 값으로 변경해준다.
- col1 / if(col2=0, NULL, col2) as avg
- 최종 나누기한 결과값은 NULL이 되므로 에러는 해결된다.
- 만든 테이블 따로 CREATE하기
- CREATE TABLE inventory.sku_grade AS (만든 테이블 복붙)
- CREATE TABLE inventory.sku_grade AS (만든 테이블 복붙)