5 분 소요

SQL 기본 문법

SELECT ~ FROM ~ WHERE

SELECT 문은 구축이 완료된 테이블에서 데이터를 추출하는 기능을 한다.
그러므로 SELECT를 아무리 많이 사용해도 기존의 데이터가 변경되지는 않는다.

SELECT의 가장 기본 형식은 SELECT ~ FROM ~ WHERE이다.
SELECT 바로 다음에는 열 이름이, FROM 다음에는 테이블 이름이 나온다.
WHERE 다음에는 조건식이 나오는데, 조건식을 다양하게 표현함으로써 데이터베이스에서 원하는 데이터를 뽑아낼 수 있다.

실습용 데이터베이스 구축

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;

기본 조회하기: SELECT ~ FROM

USE 문

SELECT 문을 실행하려면 먼저 사용할 데이터베이스를 지정해야 한다.

USE 데이터베이스 _이름;

이렇게 지정해 놓은 후에 다시 USE 문을 사용하거나 다른 DB를 사용하겠다고 명시하지 않으면 앞으로 모든 SQL 문은 ‘데이터베이스_이름’에서 수행된다.

SELECT 문의 기본 형식

SELECT 문은 처음에는 사용하기 간단하지만, 사실 상당히 복잡한 구조를 갖는다.

SELECT 열_이름
    FROM 테이블_이름
    WHERE 조건식
    GROUP BY 열_이름
    HAVING 조건식
    ORDER BY 열_이름
    LIMIT 숫자

기본적이고 핵심적인 형식을 먼저 살펴보겠다.

SELECT 열_이름
    FROM 테이블_이름
    WHERE 조건식

SELECT와 FROM

USE 데이터베이스_이름;
SELECT * FROM 테이블_이름
  • SELECT: 테이블에서 데이터를 가져올 때 사용하는 예약어 이다.
  • *: 일반적으로 ‘모든 것’을 의미한다.
    그런데 *가 사용된 위치가 열 이름이 나올 곳이므로 모든 열을 말한다.
  • FROM: FROM 다음에 테이블 이름이 나온다.
    테이블에서 내용을 가져온다는 의미이다.
  • 테이블_이름: 조회할 테이블 이름이다.

-> ‘테이블_이름’에서 모든 열의 내용을 가져와라

원래 테이블의 전체 이름은 데이터베이스_이름.테이블_이름 형식으로 표현한다.

SELECT * FROM 데이터베이스_이름.테이블 이름

하지만 데이터베이스 이름을 생략하면 USE 문으로 지정해 놓은 데이터베이스가 자동으로 선택된다.

[Output] 패널의 의미
  • 초록색 체크 표시: SQL이 정상적으로 실행되었다는 의미이다.
  • 빨간색 X 표시: SQL에 오류가 발생했다는 의미이다.
  • #: 실행한 SQL의 순번이다.
    실행한 SQL이 여러 개라면 1, 2, 3, … 순서로 증가한다.
  • Time: SQL을 실행한 시각이 표시된다.
  • Action: 실행된 SQL이 표시된다.
  • Message: SELECT 문이 조회된 행의 개수가 나온다.
    만약 오류 발생 시에는 오류 번호 및 오류 메시지가 표시된다.
  • Duration/Fetch: Duration은 SQL 문이 실행되는 데 걸린 시간(초), Fetch는 데이터베이스에서 가져온 시간(초)이다.

이번에는 해당 테이블에서 전체 열이 아닌 필요한 열만 가져오겠다.

SELECT 열_이름 FROM 테이블_이름

여러 개의 열을 가져오고 싶으면 콤마(,)로 구분하면 된다.
열 이름의 순서는 원래 테이블을 만들 때 순서에 맞출 필요 없다.

열 이름의 별칭

열 이름에 별칭(alias)을 지정할 수 있다.
열 이름 다음에 지정하고 싶은 별칭을 입력하면 된다.
별칭에 공백이 있으면 큰따옴표(“)로 묶어준다.

특정 조건만 조회하기: SELECT ~ FROM ~ WHERE

SELECT ~ FROM은 대부분 WHERE와 함께 사용한다.
WHERE는 필요한 것들만 골라서 결과를 보는 효과를 갖는다.

기본적인 WHERE 절

WHERE 절은 조회하는 결과에 특정한 조건을 추가해서 원하는 데이터만 보고 싶을 때 사용한다.

형식은 다음과 같다.

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

또는

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

관계 연산자, 논리 연산자의 사용

숫자로 표현된 데이터는 범위를 지정할 수 있다.
예를 들어 평균 키(height)가 162 이하인 회원을 검색하려면 다음과 같이 관계 연산자 <=(작거나 같다)를 사용해서 조회할 수 있다.

SELECT mem_id, mem_name
    FROM member
    WHERE height <= 162;

(관계 연산자는 >, <, >=, <=, = 등이 있다.)

2가지 이상의 조건을 만족하도록 할 수도 있다.
평균 키(height)가 165 이상이면서 인원(mem_number)도 6명 초과인 회원은 다음과 같이 논리 연산자 AND를 이용해서 조회할 수 있다.

SELECT mem_name, height, mem_number
    FROM member
    WHERE height >= 165 AND mem_number > 6;

평균 키(height)가 165 이상이거나 인원(mem_number)이 6명 초과인 회원은 다음과 같이 논리 연산자 OR를 이용해서 조회할 수 있다.
AND가 두 조건을 모두 만족해야 하는 것이라면, OR는 두 조건 중 하나만 만족해도 된다.

SELECT mem_name, height, mem_number
    FROM member
    WHERE height >= 165 OR mem_number > 6;

BETWEEN ~ AND

AND를 사용해서 평균 키(height)가 163 ~ 165인 회원을 조회해보겠다.

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

그런데 범위에 있는 값을 구하는 경우에는 BETWEEN ~ AND를 사용해도 된다.

SELECT mem_name, height
    FROM member
    WHERE height BETWEEN 163 AND 165;

IN( )

주소(addr)와 같은 데이터는 문자로 표현되기 때문에 어느 범위에 들어 있다고 표현할 수 없다.
만약 경기/전남/경남 중 한 곳에 사는 회원을 검색하려면 다음과 같이 OR로 일일이 써줘야 한다.

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

IN( )을 사용하면 코드를 훨씬 간결하게 작성할 수 있다.

SELECT mem_name, addr
    FROM member
    WHERE addr IN('경기', '전남', '경남');

LIKE

문자열의 일부 글자를 검색하려면 LIKE를 사용한다.

SELECT *
    FROM member
    WHERE mem_name LIKE '우%';

-> 이 조건은 제일 앞 글자가 ‘우’이고 그 뒤는 무엇이든(%) 허용한다는 의미이다.

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

SELECT *
    FROM member
    WHERE mem_name LIKE '--핑크';

-> 앞 두 글자는 상관없고 뒤는 ‘핑크’인 회원을 검색한다.

서브 쿼리

SELECT 안에는 또 다른 SELECT가 들어갈 수 있다.
이것을 서브 쿼리(subquery) 또는 하위 쿼리라고 부른다.

SELECT mem_name, height FROM member
    WHERE height > (SELECT height FROM member WHERE mem_name = '에이핑크');

-> 이름(mem_name)이 ‘에이핑크’인 회원의 평균 키(height)보다 큰 회원을 검색