DB/MySQL

[혼공S] SQL 기본 문법 (SELECT, FROM, WHERE, INSERT, DELETE, UPDATE)

  • -

본격적인 시작에 앞서

1차시부터 너무 많은 분들이 제 글을 읽어주셔서 놀랐습니다... 8기에는 혼공박사와 석사에 두 번 정도 제 이름에 올라갔고, 특히나 1차시에 혼공 박사가 되었는데 이번에도 그 영광(?)을 얻을 수 있을지 조금 기대하겠습니다...

SELECT ~ FROM ~ WHERE

https://www.hanbit.co.kr/support/supplement_survey.html?pcode=B6846155853

여기서 예제 파일을 다운로드했습니다

DROP DATABASE IF EXISTS market_db; -- 만약 market_db가 존재하면 우선 삭제한다.
CREATE DATABASE market_db;

USE market_db;
CREATE TABLE member -- 회원 테이블
( mem_id          CHAR(8) NOT NULL PRIMARY KEY, -- 사용자 아이디(PK)
  mem_name        VARCHAR(10) NOT NULL, -- 이름
  mem_number    INT NOT NULL,  -- 인원수
  addr              CHAR(2) NOT NULL, -- 지역(경기,서울,경남 식으로 2글자만입력)
  phone1        CHAR(3), -- 연락처의 국번(02, 031, 055 등)
  phone2        CHAR(8), -- 연락처의 나머지 전화번호(하이픈제외)
  height        SMALLINT,  -- 평균 키
  debut_date    DATE  -- 데뷔 일자
);
CREATE TABLE buy -- 구매 테이블
(  num         INT AUTO_INCREMENT NOT NULL PRIMARY KEY, -- 순번(PK)
   mem_id      CHAR(8) NOT NULL, -- 아이디(FK)
   prod_name     CHAR(6) NOT NULL, --  제품이름
   group_name     CHAR(4)  , -- 분류
   price         INT  NOT NULL, -- 가격
   amount        SMALLINT  NOT NULL, -- 수량
   FOREIGN KEY (mem_id) REFERENCES member(mem_id)
);

INSERT INTO member VALUES('TWC', '트와이스', 9, '서울', '02', '11111111', 167, '2015.10.19');
INSERT INTO member VALUES('BLK', '블랙핑크', 4, '경남', '055', '22222222', 163, '2016.08.08');
INSERT INTO member VALUES('WMN', '여자친구', 6, '경기', '031', '33333333', 166, '2015.01.15');
INSERT INTO member VALUES('OMY', '오마이걸', 7, '서울', NULL, NULL, 160, '2015.04.21');
INSERT INTO member VALUES('GRL', '소녀시대', 8, '서울', '02', '44444444', 168, '2007.08.02');
INSERT INTO member VALUES('ITZ', '잇지', 5, '경남', NULL, NULL, 167, '2019.02.12');
INSERT INTO member VALUES('RED', '레드벨벳', 4, '경북', '054', '55555555', 161, '2014.08.01');
INSERT INTO member VALUES('APN', '에이핑크', 6, '경기', '031', '77777777', 164, '2011.02.10');
INSERT INTO member VALUES('SPC', '우주소녀', 13, '서울', '02', '88888888', 162, '2016.02.25');
INSERT INTO member VALUES('MMU', '마마무', 4, '전남', '061', '99999999', 165, '2014.06.19');

INSERT INTO buy VALUES(NULL, 'BLK', '지갑', NULL, 30, 2);
INSERT INTO buy VALUES(NULL, 'BLK', '맥북프로', '디지털', 1000, 1);
INSERT INTO buy VALUES(NULL, 'APN', '아이폰', '디지털', 200, 1);
INSERT INTO buy VALUES(NULL, 'MMU', '아이폰', '디지털', 200, 5);
INSERT INTO buy VALUES(NULL, 'BLK', '청바지', '패션', 50, 3);
INSERT INTO buy VALUES(NULL, 'MMU', '에어팟', '디지털', 80, 10);
INSERT INTO buy VALUES(NULL, 'GRL', '혼공SQL', '서적', 15, 5);
INSERT INTO buy VALUES(NULL, 'APN', '혼공SQL', '서적', 15, 2);
INSERT INTO buy VALUES(NULL, 'APN', '청바지', '패션', 50, 1);
INSERT INTO buy VALUES(NULL, 'MMU', '지갑', NULL, 30, 1);
INSERT INTO buy VALUES(NULL, 'APN', '혼공SQL', '서적', 15, 1);
INSERT INTO buy VALUES(NULL, 'MMU', '지갑', NULL, 30, 4);

SELECT * FROM member;
SELECT * FROM buy;

예제 파일에 있는 코드입니다 처음부터 차근차근 살펴보겠습니다


DROP DATABASE IF EXISTS market_db; -- 데이터베이스를 삭제한다 / market_db가 존재한다면
CREATE DATABASE market_db; --market_db를 만든다

DROP문을 통해 데이터 베이스를 삭제할 수 있습니다.
IF문을 통해 DROP 할 조건을 제시하고, EXISTS는 데이터베이스가 존재하는지 나타냅니다

CREATE문을 통해 DATABASE를 생성했습니다.

USE market_db; -- market_db 선택 (앞으로 이 DB에서 진행한다)

CREATE TABLE member -- 회원 테이블
( mem_id          CHAR(8) NOT NULL PRIMARY KEY, -- 사용자 아이디(PK)
  mem_name        VARCHAR(10) NOT NULL, -- 이름
  mem_number    INT NOT NULL,  -- 인원수
  addr              CHAR(2) NOT NULL, -- 지역(경기,서울,경남 식으로 2글자만입력)
  phone1        CHAR(3), -- 연락처의 국번(02, 031, 055 등)
  phone2        CHAR(8), -- 연락처의 나머지 전화번호(하이픈제외)
  height        SMALLINT,  -- 평균 키
  debut_date    DATE  -- 데뷔 일자
);

CREATE TABLE buy -- 구매 테이블
(  num         INT AUTO_INCREMENT NOT NULL PRIMARY KEY, -- 순번(PK)
   mem_id      CHAR(8) NOT NULL, -- 아이디(FK)
   prod_name     CHAR(6) NOT NULL, --  제품이름
   group_name     CHAR(4)  , -- 분류
   price         INT  NOT NULL, -- 가격
   amount        SMALLINT  NOT NULL, -- 수량
   FOREIGN KEY (mem_id) REFERENCES member(mem_id)
);

USE 문을 통해 market_db데이터베이스를 선택했습니다. USE문을 사용하지 않으면

`market_db`.`member` 이런 식으로 작성해야 하기 때문에 번거롭습니다.

CREATE문으로 member와 buy TABLE을 생성하였습니다.

INSERT INTO member VALUES('TWC', '트와이스', 9, '서울', '02', '11111111', 167, '2015.10.19');
INSERT INTO member VALUES('BLK', '블랙핑크', 4, '경남', '055', '22222222', 163, '2016.08.08');
INSERT INTO member VALUES('WMN', '여자친구', 6, '경기', '031', '33333333', 166, '2015.01.15');
INSERT INTO member VALUES('OMY', '오마이걸', 7, '서울', NULL, NULL, 160, '2015.04.21');
INSERT INTO member VALUES('GRL', '소녀시대', 8, '서울', '02', '44444444', 168, '2007.08.02');
INSERT INTO member VALUES('ITZ', '잇지', 5, '경남', NULL, NULL, 167, '2019.02.12');
INSERT INTO member VALUES('RED', '레드벨벳', 4, '경북', '054', '55555555', 161, '2014.08.01');
INSERT INTO member VALUES('APN', '에이핑크', 6, '경기', '031', '77777777', 164, '2011.02.10');
INSERT INTO member VALUES('SPC', '우주소녀', 13, '서울', '02', '88888888', 162, '2016.02.25');
INSERT INTO member VALUES('MMU', '마마무', 4, '전남', '061', '99999999', 165, '2014.06.19');

INSERT INTO buy VALUES(NULL, 'BLK', '지갑', NULL, 30, 2);
INSERT INTO buy VALUES(NULL, 'BLK', '맥북프로', '디지털', 1000, 1);
INSERT INTO buy VALUES(NULL, 'APN', '아이폰', '디지털', 200, 1);
INSERT INTO buy VALUES(NULL, 'MMU', '아이폰', '디지털', 200, 5);
INSERT INTO buy VALUES(NULL, 'BLK', '청바지', '패션', 50, 3);
INSERT INTO buy VALUES(NULL, 'MMU', '에어팟', '디지털', 80, 10);
INSERT INTO buy VALUES(NULL, 'GRL', '혼공SQL', '서적', 15, 5);
INSERT INTO buy VALUES(NULL, 'APN', '혼공SQL', '서적', 15, 2);
INSERT INTO buy VALUES(NULL, 'APN', '청바지', '패션', 50, 1);
INSERT INTO buy VALUES(NULL, 'MMU', '지갑', NULL, 30, 1);
INSERT INTO buy VALUES(NULL, 'APN', '혼공SQL', '서적', 15, 1);
INSERT INTO buy VALUES(NULL, 'MMU', '지갑', NULL, 30, 4);

INSERT문으로 테이블에 값을 넣었습니다. INT형은 따옴표 없이, VARCHAR와 CHAR는 작은따옴표로 묶어 표현합니다.

** SELECT 문**

SELECT slect_expr -- 열 이름
    [FROM table_reference] -- 테이블 이름
    [WHERE where_condition] -- 조건식
    [GROUP BY {col_name | expr | position }] -- 열 이름
    [HAVING where_condidion] -- 조건식
    [ORDER BY {col_name { expr | position}] -- 열 이름
    [LIMIT {[offset,] row_count | rouw_count OFFSET offset}] -- 개수 제한

SELECT는

이 버튼을 눌렀을 때(execute) 가져올 열을 의미합니다.

* 은 테이블의 모든 열을 가져온다는 의미입니다.

FROM~ 은 SELECT로 가져올 열이 속한 테이블을 선택합니다.

ex)

SELECT * FROM member; -- member 테이블의 모든 열 가져오기
SELECT addr, debut_datee FROM member; -- member 테이블의 addr, debut_date 열 가져오기

WHERE문

WHERE 절은 조회하는 결과에 특정한 조건을 추가해서 조건에 해당하는 데이터를 가져옵니다.

SELECT 열 이름
FROM 테이블 이름
WHERE 조건 ;

ex)

SELECT * FROM WHERE mem_number = 4;

WHERE 절의 조건에 해당하는 데이터만 불러왔습니다

WHERE 절에는 관계 연산자와 논리 연산자도 사용할 수 있습니다.

관계연산자와 논리연산자 사용

SELECT *
FROM member
WHERE height >= 163 AND height <= 165;

위처럼 WHERE 절이 특정한 값의 범위를 나타내는 경우에는

WHERE height BETWEEN 163 AND 165;

BETWEEN a AND b로 쓸 수 있습니다


SELECT mem_name, addr
FROM market_db.member
WHERE addr = '경기' OR addr = '전남' OR addr = '경남'
;

addr이 경기, 전남, 경남인 데이터를 찾고 싶을 때에는 OR문으로도 쓸 수 있지만

IN()을 사용하여 작성할 수 있습니다.


문자열의 일부 문자를 검색하려면 LIKE를 사용합니다

SELECT *
FROM market_db.member
WHERE mem_name LIKE '우%'--제일 앞 글자가 우 인 모든 데이터
;

'%우%' --우가 들어가는 모든 데이터
'%우' --우로 끝나는 모든 데이터

교재에는 언급되어 있지 않지만 추가적으로 알아두시면 좋을 거 같습니다!


한 글자와 매치하기 위해서는 언더바를 사용합니다.

SELECT *
FROM market_db.member
WHERE mem_name LIKE '__핑크' -- 앞 두 글자는 상관 없고, 핑크로 끝나는 데이터
;

+) 서브쿼리

에이핑크 회원의 평균 키 보다 큰 회원을 구하고자 합니다

SELECT height 
FROM market_db.member 
WHERE mem_name ='에이핑크';

이 코드로 에이핑크 회원의 키는 164인 것을 알 수 있습니다.

SELECT mem_name
FROM market_db.member
WHERE height > 164;
;

이처럼 에이핑크 회원의 평균 키 보다 큰 회원을 조회하려면 두 개의 쿼리가 필요합니다.

SELECT mem_name
FROM market_db.member
WHERE height > (SELECT height FROM market_db.member WHERE mem_name ='에이핑크');
-- 괄호 안의 값은 164

위의 두 쿼리를 하나로 합쳤습니다. 아래처럼 하나의 SELECT 문에 다른 SELECT가 들어갈 수 있고, 이것을 서브쿼리라고 합니다. 서브쿼리는 2개의 SQL문을 하나로 만들어 하나의 SQL만 관리하면 되기 때문에 더 간단해집니다. 서브쿼리는 실무에서도 자주 사용된다고 하네요.

2. SELECT문 심화

** ORDER BY**

ORDER BY 절은 결과의 값이나 개수에 대해서는 영향을 미치지 않지만, 결과가 출력되는 순서를 조절합니다.

SELECT mem_id, mem_name, debut_date
FROM member
ORDER BY debut_date;

위와 같이 입력하여 실행하면 데뷔 일자가 빠른 순서대로 출력됩니다.

ORDER BY의 기본값은 오름차순이지만 ASC와 DESC로 오름차순 또는 내림차순으로 정렬할 수 있습니다

  • ASC(Ascending) : 오름차순
  • DESC(Descending) : 내림차순

ex)

SELECT mem_id, mem_name, debut_date
FROM member
ORDER BY debut_date DESC;

WHERE절과 ORDER BY절을 함께 쓸 수 있습니다. 하지만 이때 ORDER BY 절은 WHERE절 다음에 작성해야 합니다.

ex)

SELECT *
FROM member
WHERE height >= 164
ORDER BY height DESC;

여러 개의 정렬 기준을 지정할 수 있습니다.

ex)

SELECT *
FROM member
ORDER BY height DESC, dabut_date ASC;

이 쿼리는 평균키를 큰 순서대로 정렬하되, 평균 키가 같으면 데뷔 일자가 빠른 순서로 정렬하도록 합니다.

** LIMIT**

LIMIT은 출력하는 개수를 제한합니다.

SELECT *
FROM mamber
LIMIT 5; -- 5개만 출력

LIMIT의 형식은 LIMIR 시작, 개수입니다. 위의 코드처럼 작성 시 LIMIT 0, 5과 같습니다.

ex)

SELECT *
FROM member
ORDER BY height DESC -- 키가 큰 순서대로 
LIMIT 3, 2; -- 3번째부터 2번째

** DISTINCT**

DISTINCT는 조회된 결과에서 중복된 데이터를 1개만 남깁니다.

SELECT addr FROM member;

중복된 값이 그대로 출력됩니다.

SELECT DISTINCT addr
FROM member;

중복된 값이 걸러져서 나옵니다.

(5) GROUP BY

GROUP BY 절은 말 그대로 데이터를 그룹으로 묶어주는 역할을 합니다.

GROUP BY와 함께 쓰이는 집계 함수들에 대해 알아보도록 하겠습니다.

  • SUM() : 합계를 구합니다.
  • AVG() : 평균을 구합니다.
  • MIN() : 최솟값을 구합니다.
  • MAX() : 최댓값을 구합니다.
  • COUNT() : 행의 개수를 셉니다.
  • COUNT(DISTINCT) : 행의 개수를 셉니다. (중복은 1개만 인정)

같은 회원의 총 구매 개수를 구해보도록 하겠습니다.

SELECT mem_id "회원 아이디", SUM(amount) "총 구매 개수" -- " " 로 묶은 것들은 별칭입니다. 
FROM buy GROUP BY mem_id;

HAVING

HAVING절은 WHERE과 같이 출력할 데이터의 조건을 제한합니다. 하지만 WHERE절은 집계 함수에 사용할 수 없기 때문에 집계함수가 쓰였을 때 HAVING을 사용합니다. HAVING은 GROUP BY 절 뒤에 나와야 합니다.

ex)

SELECT mem_id "회원 아이디", SUM(price*amount) "총 구매 금액"
 FROM market_db.buy
 GROUP BY mem_id
 HAVING SUM(price*amount) > 1000
 ;

* 기본 미션 : 138p 2번 문제 풀고 인증하기

Q. 다음 보기 중에서 각 문항의 빈칸에 들어갈 것을 고르세요.

LIKE, DESC, ORDER BY, DISTINCT, ASC, AND, OR, >=, LIMIT

  1. SELECT * FROM member ( ) height;
  2. SELECT * FROM member ( ) 5, 2;
  3. SELECT ( ) phone1 FROM member;

답은 순서대로 ORDER BY, LIMIT, DISTINCT 입니다.

1번

height의 값이 작은 순서대로 정렬합니다.

2번

member에서 5번째에서 2번째의 항목을 출력합니다.

3번

phone1의 중복되는 항목 중 하나만 출력합니다.

** 데이터 변경을 위한 SQL 문**

SELECT문과 이번에 보게 될 INSERT, DELETE, UPDATE 문은 DMS(data Mainpulation language)에 속합니다.

DMS의 개념은 이번 챕터에서 소개되지 않지만 간단하게 설명하자면 말 그대로 데이터 조작 언어로, 데이터 베이스의 검색, 등록, 삭제, 갱신을 할 수 있는 언어입니다.

** INSERT +선택미션**

INSERT는 테이블에 행 데이터를 입력하는 기본적인 SQL문입니다.

INSERT 문의 형식은 다음과 같습니다.

INSERT INTO 테이블 (열1, 열2, ... ) VALUES (값1, 값2, ... )
-- 열은 생략 가능, VALUES 의 순서 및 개수는 테이블을 정의할 때의 열 순서 및 개수와 동일해야 함
USE market_db;
CREATE TABLE hongong1 (toy_id INT, toy_name CHAR(4), age INT);
INSERT INTO hongong1 VALUES (1, '우디', 25);
SELECT * FROM hongong1;

hongong1 테이블을 만든 뒤, 각 열에 1, '우디', 25 값을 입력했습니다

테이블에 값이 들어간 것을 확인할 수 있습니다.

AUTO_INCREMENT

AUTO_INCREMENT는 1부터 증가하는 값을 자동으로 입력해 줍니다. 해당 열은 PRIMARY KEY로 지정해야 합니다.

USE market_db;
CREATE TABLE hongong2 (
toy_id INT AUTO_INCREMENT PRIMARY KEY,
toy_name CHAR(4),
age INT
);

toy_id를 AUTO_INCREMENT로 지정한 테이블입니다

INSERT INTO hongong2 VALUES (NULL, '보핍', 25);
INSERT INTO hongong2 VALUES (NULL, '슬링키', 22);
INSERT INTO hongong2 VALUES (NULL, '렉스', 21);
SELECT * FROM hongong2;

toy_id를 NULL로 두었지만, 자동으로 숫자가 입력됩니다.


SELECT LAST_INSERT_ID();

위 코드를 통해 어느 숫자까지 증가했는지 확인할 수 있습니다.


ALTER TABLE hongong2 AUTO_INCREMENT=100;
INSERT INTO hongong2 VALUES (NULL, '재남', 35);
SELECT * FROM hongong2;

만약 자동으로 입력되는 값을 100부터 설정하시고 싶다면 ALTER TABLE을 통해 AUTO_INCREMENT를 변경할 수 있습니다.

INSERT INTO ~ SELECT

INSERT INTO ~ SELECT 구문은 다른 테이블의 데이터를 가져와 한 번에 대량으로 입력할 수 있습니다.

형식은 다음과 같습니다.

INSERT INTO 테이블_이름 (열_이름1, 열_이름2, ... ) 
 SELECT 문;

이때 SELECT문의 열 개수는 INSERT 할 테이블의 열 개수와 같아야 합니다.


CREATE TABLE city_popul (city_name CHAR(35), population INT);

city_popul 테이블을 만들었습니다.

INSERT INTO city_popul
SELECT Name, Population FROM world.city;

city_popul에 원래 있던 world의 city 테이블 값을 입력했습니다.

위 코드를 입력하면 다음과 같은 메시지가 나오고, 값이 입력됩니다.

** UPDATE**

UPDATE는 기존에 입력되어 있는 값을 수정하는 명령입니다. 기본적인 형식은 다음과 같습니다.

UPDATE 테이블_이름
SET 열1=값1, 열2=값2, ...
WHERE 조건;

ex)

UPDATE city_popul
SET city_name='서울'
WHERE city_name='Seoul';
SELECT * FROM city_popul WHERE city_name='서울';

UPDATE문을 통해 city_name이 Seoul인 것을 서울로 바꿨습니다.

UPDATE문에 WHERE 절을 사용하지 않으면 모든 행의 데이터가 변경됩니다. 모든 행의 데이터를 바꾸고 싶을 때에는 WHERE 절 없이 사용할 수 있습니다.

DELETE +선택미션

DELETE는 행 단위로 삭제하며 WHERE가 없으면 전체 행이 삭제됩니다.

형식은 다음과 같습니다.

DELETE FROM 테이블이름 WHERE 조건;

ex)

DELETE FROM city_popul
WHERE city_name LIKE 'New%';

New로 시작하는 city_name을 삭제하였습니다.

마무리

확실히 1주 차보다 더 많은 내용이 담겨있습니다. 교재에서도 두 번 보는 것을 추천하고 있네요.

다음 챕터인 SQL고급 문법을 숙지하기 위해서는 철저하게 공부하는 것이 좋을 거 같습니다.

제 글 읽어주셔서 감사합니다.

'DB > MySQL' 카테고리의 다른 글

[MySQL] 스토어드 프로시저와 SQL의 파이썬 연결  (0) 2023.02.14
[MySQL] 인덱스란 무엇일까?  (0) 2023.02.06
[MySQL] 테이블과 뷰  (0) 2023.01.30
[MySQL] SQL 고급 문법  (0) 2023.01.16
[혼공S] 데이터 베이스와 SQL  (0) 2022.12.29
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.