관계형 데이터베이스 시스템(RDBMS)에서 데이터를 조회 및 처리하기 위해 사용하는 구문
RDB의 종류는 여러가지이기 때문에, 제품에 따라 SQL 문법이 조금씩 다를 수 있지만 대체로 한 제품의 SQL 사용이 익숙하다면 다른 제품에서도 유사하게 사용할 수 있다.
SQL을 사용해야하는 이유는, 실무에서 데이터를 다룰 때 거의 항상 DB에서 직접 조회하고 원하는 형태로 가공하여 꺼낼 수 있어야하기 때문이다.
미국표준협회(ANSI)에서 정의한 표준 SQL 작성 방법
DB 제품 종류에 상관없이 공통적으로 사용할 수 있다.
이번 교과 과정에서 배우게될 구문이다.
데이터의 구조를 다루기 위한 명령어이다.
데이터베이스 또는 테이블 등을 생성/수정/삭제 할 수 있다.
CREATE, ALTER, DROP 등이 DDL에 해당한다.
CREATE DATABASE mydb;
CREATE 명령어를 사용해 DB를 생성한 결과이다.
MySQL에서는 명령어와 변수명의 대소문자를 구분하지는 않지만, 가독성을 위해 명령어는 대문자 변수는 소문자 등 규칙을 정해놓는 것이 좋다. (실무에서는 당연히 사내 규약을 따름)
데이터를 조작하는 명령어이다.
테이블에 있는 데이터를 생성/수정/삭제할 수 있다. (INSERT/UPDATE/DELETE)
테이블을 조회하는 SELECT 명령어도 테이블(뷰)를 만들어내는 것이 가능하기 때문에 DML에 해당한다.
DBMS에서 데이터 객체들의 권한을 관리하는 명령어이다.
GRANT, REVOKE, DENY 등이 DCL에 해당한다.
테이블에서 데이터를 가져올 데이터를 선택하거나 문자열, 수식, 함수 등을 출력할 수 있다.
SELECT *
을 이용하면 모든 컬럼을 선택하여 가져올 수 있다. (권장하지는 않음)
테이블에서 데이터를 가져오기 위해서는 반드시 FROM
과 함께 사용해야 하며, MySQL 기준으로 테이블의 데이터가 아닐 경우 FROM
을 생략할 수 있다.
출력할 컬럼명을 변경하고 싶다면 AS
구문을 이용할 수 있다.
SELECT 10 + 20 AS result
-- customer 테이블의 모든 컬럼 가져오기
SELECT *
FROM customer;
-- customer 테이블의 고객 아이디, 이름, 전화번호 가져오기
SELECT customer_id, customer_name, phone
FROM customer;
SET @<변수명> = <변수에 저장할 값>
SQL에서도 변수를 활용할 수 있는데 이를 위해 SET
명령어와 @
를 이용한다.
저장된 변수는 @<변수명>
으로 SELECT
등을 활용해 출력할 수 있다.
-- 변수 값 출력
SET @Today = CURDATE();
SELECT @Today;
테이블에서 추출할 행의 조건을 선택할 수 있다.
-- employee 테이블에서 emp_id가 ‘S0001’인 모든 데이터 조회
SELECT *
FROM employee
WHERE emp_id = 'S0001';
WHERE 조건문에서 값을 비교하는데 쓰이는 연산자이다.
=
, >
, <
, >=
, <=
, <>
등 일반적으로 쓰이는 비교 연산자를 사용할 수 있다.
LIKE
는 문자열의 비교를 위해 사용하는 연산자이다.
다양한 조건으로 문자열을 검색할 수 있다.
김%
: 김으로 시작하는 문자열%김%
: 김을 포함하는 문자열%김
: 김으로 끝나는 문자열_
: 아무 문자 1자를 의미한다.김__
: 김으로 시작하는 3글자 문자열____@%
: 아이디가 4자인 이메일NOT
과 같은 부정의 의미를 갖는 연산자와 OR
, AND
와 같은 여러개의 조건을 합치기 위한 연산자를 사용할 수 있다.
특히 NOT
연산자는 다양한 연산자의 앞뒤로 붙어 활용할 수 있다.
<열 이름> IN ('값1', '값2, '값3')
: 열의 값이 값1, 값2, 값3인 데이터를 출력OR
대신 사용할 수 있는 연산자로, 조건에 열 이름을 반복해서 입력해야하는 번거로움을 해결한다.
<열 이름> BETWEEN <시작 값> AND <끝 값>
: 시작 값 이상, 끝 값 이하의 범위를 출력시작과 끝값을 지정할 수 있는 연산자이다.
열 이름을 두번 지정할 필요가 없기 때문에 간편하고 가독성 역시 향상된다.
AND
를 통해 시작값과 끝값을 구분한다.
번외 : 바람직한 형태의 쿼리
반드시 필요한 행과 열만을 조회할 수 있는 쿼리가 가장 바람직한 쿼리이다.
데이터베이스의 성능은 곧 작업 수행 속도를 의미하는데, 불필요한 행, 열을 조회하면 그만큼 소요되는 시간이 증가하기 때문
특히*
사용을 지양하자.
번외 : CHAR, VARCHAR
CHAR
는 길이가 고정된 문자열 데이터 타입을 말한다.
VARCHAR
는 길이가 가변인 문자열 데이터 타입을 말한다.
예를들어 VARCHAR(10)은 최대 10글자까지 가변적으로 저장 가능한 문자열을 말한다.CHAR, VARCHAR 모두 정해진 글자수를 초과하지 않으면 데이터 저장이 가능하다.
그러나 VARCHAR를 사용하면 남는 공간을 할당하지 않기때문에 입력될 글자수를 모를 경우 유리하다.
반면 CHAR는 할당된 공간보다 데이터가 적게 입력되어도 항상 똑같은 공간을 사용하기 때문에 공간의 낭비가 발생할 수 있다.VARCHAR의 단점은 데이터의 실제 크기를 따로 저장해야한다는 것이다.(오버헤드) 이로 인해 같은 크기의 데이터라면 CHAR보다 VARCHAR를 사용할 때 더 많은 공간이 필요하다.
NULL은 알 수 없는 값(Unknown Value)이라는 뜻을 가진다.
알 수 없는 값을 비교한다는 것은 불가능하기 때문에 오직 IS NULL
, IS NOT NULL
을 통해 NULL 값 조건을 확인할 수 있다.
IFNULL(<컬럼 이름>, <대체값>)
: 해당 컬럼을 출력할 때 NULL인 값은 대체값으로 대체하여 출력한다.SELECT
절에서 데이터가 NULL인 상태로 출력되는 것을 원치 않을 때 사용한다.
IFNULL
은 MySQL에서 사용하는 함수명으로 MSSQL은 ISNULL()
, 오라클은 NVL()
이라는 함수명을 사용한다.
COALESCE(<값 1>, <값 2>, <값 3>, ...)
: 주어진 인자 중에서 NULL이 아닌 첫번째 값을 반환하는 함수IFNULL
과 유사한 기능을 하는 함수로, 인자로 컬럼명을 지정하면 IFNULL
처럼 사용할 수 있다.
제품 별로 함수 이름이 다른 경우도 없으므로 되도록 사용을 권장하는 함수이다.
번외) MySQL의 더하기 연산
SQL에서는 문자열의 더하기 연산이 불가능하다.
더하기 연산은 오직 숫자에만 적용이되며, 숫자로 변환이 불가능한 문자열은 0으로 형변환 한다.
- ‘10’ + ‘20AX’ = 30 → 앞에 형변환이 가능한 20만 숫자로 변환되어 계산 된다
- ‘10’ + ‘AX20’ = 10 → 문자가 제일 앞에 나온 경우 문자로 인식해서 0으로 변환된다.
이는 MySQL 기준으로, DBMS 제품 별로 처리하는 방식이 다르다.
문자열을 붙이기 위해서는
CONCAT()
함수를 이용할 수 있다.
CONCAT는 숫자도 상관없이 문자열 처럼 붙인다.
NULL과 붙일 경우 NULL이 된다.
ORDER BY <열 이름> <정렬방법>
정렬 방법에 따라 결과를 정렬하여 출력한다.
정렬 방법은 ASC
(오름차순)과 DESC
(내림차순)이 있다.
일반적으로 모든 쿼리 처리를 끝낸 뒤 최종적으로 정렬 방법을 결정하므로, 다른 쿼리로 인해 정렬 결과가 섞이지 않는다.
-- retire_date가 NULL인 데이터를 이름순으로 오름차순 정렬하여 출력
SELECT emp_name, emp_id, gender, dept_id, hire_date, phone
FROM employee
WHERE retire_date IS NULL
ORDER BY emp_name ASC;
ORDER BY <열 이름1> <정렬방법1>, <열 이름2>, <정렬방법2>, ...
위와 같은 방식으로 복합 정렬도 가능하다.
CASE WHEN <조건문> THEN <참일 때 출력할 값> ELSE <거짓일 때 출력할 값> END
중첩이 가능한 조건문으로, 조건문의 만족 여부에 따라 출력할 값을 다르게 지정할 수 있다.
ELSE
는 선언하지 않아도 되며, 이 경우 모든 조건을 불만족할 때 NULL
을 출력한다. 하지만 가독성을 위해 되도록 ELSE NULL
형태로 명시하는 것을 권장한다.
END
로 종료 선언을 해주어야 조건문을 빠져나온다.
-- Q) 급여 크기를 상, 중, 하로 구분
SELECT emp_name, emp_id, dept_id,
CASE WHEN salary >= 8000 THEN '상'
WHEN salary >= 7000 THEN '중'
ELSE '하' END AS 'salary'
FROM employee;
WHEN
을 중첩할 경우 Else if
와 유사하게 작동하므로, 경계값을 모두 지정할 필요가 없다.
IF(<조건문>, <참일 때 출력할 값>, <거짓일 때 출력할 값>)
조건문이 하나만 필요할 경우 CASE
대신 간편하게 사용할 수 있는 조건문이다.
삼항 연산자와 유사한 형태로 사용한다.