[RealMySQL] 기본적인 문법
MySQL/RealMySQL

[RealMySQL] 기본적인 문법

MySQL에서는 두 종류의 SQL문이 있습니다.

먼저 DB(스키마)나, 테이블의 구조를 변경하기 위한 문장인 DDL(Data Definition Language)과,

테이블의 데이터를 조작(읽고, 쓰기)하기 위한 문장을 DML(Data Manipulation Language)이 있습니다.

 

DML

DML에는 우리가 자주 얘기하는 크게 CRUD와 그 외로 나뉘게 됩니다.

대분류 기능 쿼리
CRUD 생성, 저장(CREATE) INSERT
조회(READ) SELECT
변경(UPDATE) UPDATE
삭제(DELECT) DELETE
비표준 SQL DBMS마다 다름

비표준 SQL에 관해서는 각 DMBS의 Reference를 참고하시면 됩니다.

 

MySQL 기본설정 및 문법

(MySQL 기본설정에 관한 포스트는 다음을 참고하시기 바랍니다.)

한글을 배울때 문법에서 가장 먼저 5언 9품사를 배우는 것처럼, MySQL에서도 기본적인 문법 틀이 있습니다.

하나하나 살펴보도록합시다.

이와 관련된 레퍼런스들을 해석해 포스팅 했으니 자세한 정보를 원하시면 보시는것도 추천합니다.

 

1. 영문 대소문자 구분

MySQL 서버는 설치된 운영체제에 따라 테이블명의 대소문자를 구분합니다. (디스크 디렉터리나 파일로 매핑되기 때문)

 

윈도우 - 대소문자 구분 X

유닉스 계열 - 대소문자 구분 O

 

그렇기 때문에 운영체제를 변경하는 일이 생기는 경우 주의하셔야 합니다.

이를 방지하기 위해서는 'lower_case_table_name' 시스템 변수를 설정하면 됩니다.

변수 값 설명
lower_case_table_name = 0 대소문자를 구분한다.
lower_case_table_name = 1 모두 소문자로 저장하게 된다.
lower_case_table_name = 2 저장은 대소문자를 구분하나, 쿼리에서는 대소문자를 구분하지 않는다.

(사실 베스트는 애초에 대소문자를 섞어 쓰지 않고 통일하는 것입니다.)

 

 

2. MySQL 예약어

데이터베이스(스키마), 테이블, 칼럼의 이름을 예약어와 같은 키워드로 생성하는 경우, 항상 역따옴표(`)나, 쌍(큰)따옴표(")를 사용해야 합니다. (이외의 경우 따옴표를 쓰지 않거나, 역따옴표 사용)

이를 무시하는 경우, 삐끗하다 '단순히 문법이 틀리다'는 형식의 에러만 출력되기 때문에 디버깅이 힘들어지게 됩니다.

베스트는 예약어를 피해서 생성하는 것이지만, 예약어를 모두 외우는 것도 힘드니, 따옴표를 생성하지 않고, 테이블을 생성해 오류가 발생하면 이를 피하면 됩니다.

그림1. 예약어와 같은 이름을 가진 테이블 생성 예시

 

3. SQL 표기 읽기

기본적인 문법은 다음을 참고하시면 됩니다. 여기서는 대표적인 부분만 짚고 넘어가겠습니다.

 

대소문자

SQL 키워드는 대소문자를 구분하지 않습니다.

 

 

대괄호( '[', ']' )

대괄호는 해당 키워드나, 표현식이 선택사함임을 명시합니다. 대괄호로 묶인 키워드나 표현식은 없어도 문법적인 오류를 일으키지 않고(없으면, 안쓰면 그만), 있어도 문법적인 오류가 발생하지 않습니다.(틀리면, 안쓰면 그만)

DROP TABLE [IF EXISTS] tbl_name

 

 

중괄호( '{', '}' )

아래에서 설명할 파이프와 같이 사용되는 특수문자입니다. 여러 선택사항 중 반드시 하나를 꼭 써야 하는 경우에 사용합니다.

 

 

파이프( '|' )

Or의 의미를 가지는 특수문자입니다. 선택사항은 딱 2개만 쓸 수 있지 않고 그 이상도 사용이 가능합니다.

-- 선택해도 안해도 되는 경우 (대괄호 사용)
[키워드1 | 키워드2 | 키워드3]

-- 반드시 하나 선택해야 하는 경우 (중괄호 사용)
{키워드1 | 키워드2 | 키워드3}

 

 

줄임표( '...' )

줄임표는 일반적으로 키워드나 표현식이 반복되는 복잡한 구문을 축약하기 위해서 명령문의 일부가 생력되었음을 알리는 특수문자입니다.

-- 반복되는 경우
RESET reset_option [,reset_option] ...

이런 형식은 자바에서도 많이 보셨을겁니다. (String... strs)

 

 

 

4. 타입 표기

자세한 정보들은 해당 문서를 참고하시기 바랍니다.

문자열

SQL 표준에서 문자열은 항상 작은(홑)따옴표(')를 사용합니다.

MySQL에서는 추가적으로 큰(쌍)따옴표(") 역시 문자열로 표기할 수 있습니다.

SELECT * FROM member WHERE name = '이름1';
SELECT * FROM member WHERE name = "이름1";

문자열에 따옴표가 들어가는 경우

SQL 표준에서는 따옴표를 두번 입력해야 합니다.

MySQL에서는 두 종류의 따옴표를 조합해서 사용하면, 두번 입력하는 과정을 생략할 수 있습니다.

추가적으로 NO_BACKSLASH_ESCAPES모드가 활성화 되지 않는 한 이스케이프 (\', \")를 사용해서도 표현할 수 있습니다.

-- SQL 표준에서는 따옴표를 두번 입력해야 한다.
SELECT * FROM member WHERE name = '이름''1';

-- MySQL에서는 두 종류의 따옴표를 조합해 이를 생략할 수 있다.
SELECT * FROM member WHERE name = "이름'1";

-- 같은 따옴표라면 역시 두번 입력해야 한다.
SELECT * FROM member WHERE name = "이름""1";

문자열 이스케이프

 

추가적으로 예약어와 식별자가 겹치는 경우입니다.

오라클이나 MS-SQL에서는 쌍따옴표, 역따움표 그리고 대괄호를 감싸서 충돌을 방지합니다.

MySQL에서는 역따옴표를 감싸서 사용합니다.

해당 기능은 SQL 모드를 조정해서 수정이 SQL표준과 최대한 비슷하게 바꿀 수 있습니다.

-- 역 따옴표를 사용하는 MySQL
CREATE TABLE test (`table` VARCHAR(20) NOT NULL);

 

 

숫자

숫자를 사용할때는 그냥 아무 가공도 하지 않고 숫자 그대로 사용하시면 됩니다.

물론 따옴표를 사용하더라도 안의 내용물이 숫자라면 문자열이 아닌 숫자 타입으로 캐스팅을 해주나 성능이 떨어지게 될 것입니다.

단, WHERE절과 같이 비교를 할떄는 주의를 해야 합니다.

SELECT * FROM test WHERE test_number = 1000;
SELECT * FROM test WHERE test_String = '1000';

일단 MySQL에서는 이렇게 내용물이 숫자라면 반드시 캐스팅이 우선적으로 수행됩니다. 그래서 두번째 SQL문은 해당 컬럼의 문자열들을 모두 숫자로 캐스팅 후 비교를 하기 때문에 해당 결과가 참인 인덱스를 발견을 한다 하더라도, 사용하지 못합니다.

그래서 베스트는 숫자는 숫자 타입 컬럼에만 사용하고, 문자열은 문자열에만 사용을 하는 것입니다.

두번째로는 캐스팅 후 사용이 가능합니다. 하지만, 이 경우 성능관리에 주의를 기울여야 합니다.

 

 

날짜

SQL 표준에서는 문자열을 DATE 타입으로 변환을 해야 합니다. (Oracle : TO_DATE 함수, 등등)

MySQL에서는 문자열이 정해진 형태의 날짜 포맷으로만 표기가 된다면, 자동으로 DATE나, DATETIME으로 변환을 해 줍니다.

-- SQL 표준은 내장 함수를 통한 변환 필요.
-- MySQL
SELECT * FROM test_table WHERE test_date = STR_TO_DATE('2021-09-29', '%Y-%m-%d');
-- oracle
SELECT * FROM test_table WHERE test_date = TO_DATE('2021-09-29', 'yyyy-mm-dd');


-- MySQL에서는 포맷만 같으면 자동 변환
SELECT * FROM test_table WHERE test_date = '2021-09-29';
SELECT * FROM test_table WHERE test_date = '20210929';
SELECT * FROM test_table WHERE test_date = 20210929;

-- 느슨한 구문인 MySQL의 경우 어떤 특수문자든 가능
SELECT * FROM test_table WHERE test_date = '2021-09-29';
SELECT * FROM test_table WHERE test_date = '2021/09/29';
SELECT * FROM test_table WHERE test_date = '2021^09^29';

 

입력은 표준 SQL 구문에 해당하는 ODBC 구문역시 인식합니다.

{ d 'str' }
{ t 'str' }
{ ts 'str' }

 

주의사항

MySQL에서 TIMESTAMP 연도 범위는 1970에서 2038까지 입니다.

 

 

불리언

TINYINT 타입을 통해 True/False를 구분하며, 동의어로 BOOL, BOOLEAN 타입이 있습니다.

BOOL이나, BOOLEAN 타입으로 생성을 하더라도, 테이블에서는 TINYINT 타입으로 생성이 됩니다.

TINYINT는 1바이트로 -128 ~ 127 까지 저장이 가능합니다.

BOOL, BOOLEAN은 TINYINT의 동의어

 

이들을 조회하면 결과는 true false가 아닌, 1 또는 0으로 나옵니다. (true가 1, false가 0으로 매핑)

TRUE, FALSE는 각각 1과 0에 매핑되어 있다.

 

주의할 점은 1과 0만 TRUE와 FALSE로 매핑이 되어 있다는 것입니다.

1과 0을 제외하면 TRUE FALSE로 매핑된 값이 없다.

다음 그림과 같이 4는 true로 매핑되어 있지 않는 것을 알 수 있습니다.

그렇기 때문에 불리언 타입을 쓰고 싶다면, ENUM 타입으로 관리하는 것이 더 편하고 명확할 수 있습니다.

 

 

 

 

5. 연산자와 내장함수

내장함수의 자세한 정보는 다음을 참고하시면 됩니다.

여기서는 연산자만 다루겠습니다.

 

비트 연산자

비트 연산자는 비트(bit) 단위로 논리 연산을 할 때 사용하는 연산자입니다. 5.7버전과 8.0버전이 다르기떄문에 주의가 필요합니다.

연산자 설명
& 대응되는 비트가 모두 1이면 1을 반환 (AND 연산)
>> 부호를 유지하면서 지정한 수만큼 비트를 전부 오른쪽으로 이동 (right shift 연산)
<< 지정한 수만큼 비트를 전부 왼쪽으로 이동
(left shift 연산)
^ 대응되는 비트가 서로 다르면 1을 반환 (XOR 연산)
BIT_COUNT( ) 해당 숫자형의 비트를 카운트
(예시 : BIT_COUNT(15)=4)
| 둘중 하나라도 1이면 1을 반환 (OR 연산)
~ 1과 0을 반전 (비트 NOT 연산)

 

비교 연산자

기본적으로 NULL은 IS NULL을 제외하고는 비교가 불가능합니다. 하지만 NULL-SAFE의 경우에는 NULL 비교가 가능해집니다!

연산자 설명
> ~ 보다 크다
>= ~ 보다 크거나 같다
<>, != 같지 않다를 위한 연산자 (통일해서 사용 추천)
<=> 동등 비교 연산자 (NULL-SAFE)
= 동등 비교 연산자
mysql> SELECT 1 <=> 1, NULL <=> NULL, 1 <=> NULL;
        -> 1, 1, 0
mysql> SELECT 1 = 1, NULL = NULL, 1 = NULL;
        -> 1, NULL, NULL

 

논리 연산자 

연산자 설명
AND, && AND의 의미를 가짐
OR, || OR의 의미를 가짐
NOT, ! BOOLEAN 연산의 결과를 반대로 만드는 연산자
반드시 연산의 결과를 정확히 알 때만 사용할 것!
XOR 배타적 논리합 '(a AND (NOT b)) OR ((NOT a) and b)'의미를 가짐

우선순위는 NOT AND OR 순입니다. XOR의 경우 다음 밴다이어그램을 참고하면 이해가 쉽습니다.

XOR 밴다이어그램

 

이외에도 다른 연산자들이 있기 때문에 필요한 것이 있으면 Reference를 찾아봅시다.