danbibibi
article thumbnail
Published 2023. 2. 13. 01:24
MySQL 정리 CS/데이터베이스

MySQL

 

  • 세계에서 가장 많이 쓰이는 오픈 소스의 관계형 데이터베이스 관리 시스템
  • 다양한 운영체제에서 사용할 수 있으며, 여러 가지의 프로그래밍 언어를 지원
  • 크기가 큰 데이터 집합도 빠르고 효과적으로 처리할 수 있음
  • 널리 알려진 표준 SQL 형식을 사용
  • MySQL 응용 프로그램을 사용자의 용도에 맞게 수정할 수 있음
  • 키워드와 구문에서 대소문자를 구분하지 않음
  • DB 서버마다 독립적인 스토리지를 할당하는 방식을 사용

 

MySQL 장점

  • 용량 & 처리 : 적은 용량 차지(1MB RAM), 매우 적은 오버 헤드, 빠른 처리 속도로 대용량 데이터 처리에 용이
  • 접근성 : 다른 데이터 관리 툴에 비해 구조가 간단하여 사용이 쉬움
  • 지원 : 다양한 프로그래밍 언어와 통합 가능, 거의 모든 운영체제에서 사용을 지원
  • 유연성 : 유연하고 확장이 가능한 구조
  • 가격 (오픈소스 - 무료 / 상업용 - 유료)

 

MySQL 단점

  • 복잡한 쿼리 시 성능 저하
  • 트랜잭션 지원이 완벽하지 않음
  • 사용자정의 함수(UDF)의 사용이 쉽지 않고 유연하지 않음

 

MySQL 사용이 적합한 경우

  • 분산 작업이 필요한 경우

        : MySQL의 복제 기능 지원은 Primary-Secondary

          또는 Primary-Primary 구조와 같은 분산 데이터베이스 설정에 적합함

 

  • 웹 사이트 및 웹 애플리케이션

        - MySQL은 인터넷을 통해 많은 웹 사이트와 애플리케이션을 지원함

        - 설치가 쉽고, 속도가 빠르면며, 확장성이 좋음

 

  • 향후 성장이 예상되는 제품

        : MySQL의 복제 기능 지원은 수평적 확장에 도움이 될 수 있음

 

💡 MySQL의 복제 기능

 

MySQL 사용이 부적합한 경우

  • SQL 준수가 필요한 경우 

        : MySQL은 표준 SQL을 완전히 준수하지 않음

 

  • 동시성과 대용량 데이터 볼륨이 요구되는 경우

        - MySQL은 일반적으로 읽기가 많은 작업에서 잘 수행되지만,

          동시에 읽기와 쓰기 작업이 일어나는 경우는 문제가 될 수 있음

 

        - 응용프로그램에 한 번에 많은 사용자가 데이터를 쓰는 경우,

          PostgreSQL과 같은 다른 RDBMS가 더 나은 선택이 될 수 있음

 

 

주석

# 한줄 주석

-- 한줄 주석

/* 여러줄
주석*/

 

데이터 타입

1. 숫자 타입

  • 정수 타입 (TINYINT, SMALLINT, MEDIUMINT, INT, BIGINT)
  • 고정 소수점 타입 (DECIMAL)
  • 부동 소수점 타입 (FLOAT, DOUBLE)
  • 비트값 타입 (BIT)

2. 문자열 타입

  • CHAR (고정 문자열)
  • VARCHAR (가변 길이 문자열)
  • BINARY, VARBINARY
  • BLOB, TEXT
  • ENUM (미리 정의한 집합 안의 요소 중 하나만을 저장 가능)
  • SET (미리 정의한 집합 안의 요소 중 여러 개를 동시에 저장할 수 있는 타입)

3. 날짜와 시간 타입

  • DATE(날짜, 'YYYY-MM-DD')
  • DATETIME (날짜 + 시간, 'YYYY-MM-DD HH:MM:SS')
  • TIMESTAMP ('1997-01-01 00:00:01' UTC부터 시작하는 초수')
  • TIME (시간, 'HH:MM:SS')
  • YEAR (YEAR(4) : 4자리)

 

연산자

1. 산술 연산자

 +  -   *   /   DIV  % (or)
 MOD

2. 대입 연산자

  •  = (SET 문이나 UPDATE 문의 SET 절에서만 대입연산자로 사용)
  • := (비교 연산자로 해석되지 않는 대입 연산자)

3. 비교 연산자 

 =   != < , > ,  <=, >=
  • IS (왼쪽 피연산자와 오른쪽 피연산자가 같으면 참을 반환)
  • IS NOT
  • IS NULL (피연산자의 값이 NULL이면 참을 반환)
  • IS NOT NULL
  • BETWEEN a AND B (a~b 사이면 참을 반환, a와 b 포함)
  • NOT BETWEEN a AND B
  • IN() (피연산자의 값이 인수로 전달받은 리스트에 존재하면 참을 반환)
  • NOT IN()

4. 논리 연산자

  AND
 (&&)
 OR
 ( || )
 XOR  NOT
 (!)

5. 비트 연산자

 AND 연산  OR 연산  XOR 연산 NOT 연산  left shift 연산  right shift 연산
 &  |  ^  ~  <<  >>

* MySQL에서는 '0'과 '1'로만 이루어진 문자열 앞에 'b'를 붙여 2진수를 표현

 

제약 조건

: 데이터의 무결성을 지키기 위해, 데이터를 입력받을 때 실행되는 검사 규칙

  • NOT NULL : NULL 값 저장 불가
  • UNIQUE : 고유한 값을 가져야 함
  • PRIMARY KEY :  NOT NULL + UNIQUE
  • FOREIGN KEY : 하나의 테이블을 다른 테이블에 의존하게 만듦
  • DEFAULT : 필드의 기본값을 설정해야 함

 

* CREATE 문으로 테이블을 생성할 때나 ALTER 문으로 필드를 추가할 때 설정할 수 있음

* 아래와 같은 방식으로 사용

# create
CREATE TABLE Test(
    ID INT NOT NULL,
    Name VARCHAR(30),
    ReserveDate DATE,
    RoomNum INT
);

# alter
ALTER TABLE Reservation 
MODIFY COLUMN Name VARCHAR(30) NOT NULL;

 

SQL 분류

 

CREATE

  • 새로운 데이터베이스 생성
  • CREATE TABLE 테이블이름( 필드이름1 필드타입1, 필드이름2 필드타입2, ... )
CREATE TABLE Test
(
    ID INT,
    Name VARCHAR(30),
    ReserveDate DATE,
    RoomNum INT
);

 

ALTER

  • 데이터베이스와 테이블  내용을 수정
  • ALTER DATABASE 
  • ALTER TABLE
  • ADD, DROP, MODIFY COLUMN
-- 새로운 필드 추가
ALTER TABLE Reservation
ADD Phone INT; # (ADD COLUMN 컬럼명 타입) - COLUMN 키워드 생략 가능

-- 필드 삭제
ALTER TABLE Reservation
DROP RoomNum;

-- 필드 타입 변경
ALTER TABLE Reservation
MODIFY COLUMN ReserveDate VARCHAR(20);

 

DROP

  • 데이터베이스와 테이블 삭제
  • DROP DATABASE 데이터베이스이름
  • DROP TABLE 테이블이름
  • TRUNCATE TABLE (테이블 자체가 아닌 테이블의 데이터만을 지우고 싶은 경우)
DROP DATABASE Hotel;

DROP TABLE Reservation;
TRUNCATE TABLE Reservation;

-- 데이터베이스나 테이블이 존재하지 않아서 발생하는 에러 방지
DROP DATABASE IF EXISTS Hotel;
DROP TABLE IF EXISTS Reservation;

 

INSERT

  • 테이블에 새로운 레코드 추가
  • INSERT INTO 테이블이름(필드이름1, 필드이름2, ...) VALUES (데이터값1, 데이터값2, ...)
  • INSERT INTO 테이블이름 VALUES (데이터값1, 데이터값2, 데이터값3, ...)
* 2번째 경우에는 데이터베이스의 스키마와 같은 순서대로 필드의 값이 자동 대입
* 아래 필드 값은 생략 가능 

1. NULL을 저장할 수 있도록 설정된 필드 
2. DEFAULT 제약 조건이 설정된 필드
3. AUTO_INCREMENT 키워드가 설정된 필드
INSERT INTO Reservation(ID, Name, ReserveDate, RoomNum)
VALUES(5, '이순신', '2016-02-16', 1108);


-- 추가하는 레코드가 반드시 모든 필드의 값을 가져야 할 필요는 없음
-- 비어 있는 필드는 NULL 값을 가짐
INSERT INTO Reservation(ID, Name)
VALUES (6, '김유신');

 

UPDATE

  • 테이블의 레코드 내용 수정
  • 해당 테이블에서 WHERE 절의 조건을 만족하는 레코드의 값만 수정
  • UPDATE 테이블이름 SET 필드이름1=데이터값1, 필드이름2=데이터값2, ... WHERE 필드이름=데이터값
UPDATE Reservation
SET RoomNum = 2002
WHERE Name = '홍길동';

-- WHERE 절 생략
-- 모든 레코드의 RoomNum 필드의 값이 2002로 변경됨
UPDATE Reservation
SET RoomNum = 2002;

 

DELETE

  • 테이블의 레코드 삭제
  • DELETE FROM 테이블이름 WHERE 필드이름=데이터값
DELETE FROM Reservation
WHERE Name = '홍길동';

-- WHERE절 생략
-- 테이블에 저장된 모든 데이터 삭제
DELETE FROM Reservation

 

SELECT

  • 원하는 레코드를 가져옴
  • SELECT 필드이름 FROM 테이블이름 [WHERE 조건]
-- 해당 테이블의 모든 필드 선택 (*)
SELECT *
FROM Reservation;

-- WHERE 절을 사용하여 검색할 레코드의 조건을 설정할 수 있음
SELECT *
FROM Reservation
WHERE Name = '홍길동';

-- AND , OR 을 통해 여러개의 조건을 같이 명시 가능
SELECT *
FROM Reservation
WHERE ID <= 3 AND ReserveDate > '2016-02-01';

-- 특정 필드만 선택
SELECT Name, RoomNum
FROM Reservation;

-- 조건을 만족하는 특정 필드만 선택
SELECT Name, ReserveDate 
FROM Reservation
WHERE ID <= 3 AND ReserveDate > '2016-02-01';

-- 중복 값 제거 (DISTINCT)
SELECT DISTINCT Name
FROM Reservation;

-- 선택한 결과 정렬
-- default : ASC (오름차순) 
SELECT * 
FROM Reservation
ORDER BY ReserveDate DESC; -- 내림차순

-- 쉼표(,)를 사용하여 여러 필드의 데이터를 한 번에 정렬
SELECT *
FROM Reservation
ORDER BY ReserveDate DESC, RoomNum ASC;

-- 별칭(alias) 사용
-- 결과 예 ) 
-- ReserveDate | ReserveInfo
-- 2022-01-05  | 2014 : 홍길동
-- CONCAT() : 인수로 전달받은 문자열을 모두 결합하여 하나의 문자열로 반환하는 함수
SELECT ReserveDate, CONCAT(RoomNum, " : ", Name) AS ReserveInfo
FROM Reservation;

 

흐름 제어

1. CASE 

  • 값 비교
  • 표현식의 논리 값에 따라 다른 값 반환
  • CASE ... WHEN ... THEN ... END
select employee_id, first_name, salary,
    case when salary > 15000 then '고액연봉'
         when salary > 8000 then '평균연봉'
         else '저액연봉'
    end "연봉등급"
from employees;
SELECT ANIMAL_ID, NAME,
CASE 
    WHEN (SEX_UPON_INTAKE LIKE 'Neutered%') OR (SEX_UPON_INTAKE LIKE 'Spayed%')THEN 'O'
    ELSE 'X'
    END AS '중성화'
FROM ANIMAL_INS 
ORDER BY ANIMAL_ID;

 

2. IF()

  • 조건에 따라 다른 값으로 조회하고 싶은 경우
  • IF(조건문, TRUE, FALSE)
SELECT ANIMAL_ID, NAME,
IF((SEX_UPON_INTAKE LIKE 'Neutered%') OR (SEX_UPON_INTAKE LIKE 'Spayed%'), "O", "X")  AS "중성화" 
FROM ANIMAL_INS 
ORDER BY ANIMAL_ID;

 

3. IFNULL()

  • IFNULL(expr1, expr2)
  • expr1이 NULL인 경우, expr2 반환
select employee_id 사번, first_name 이름, salary 급여, salary*12 연봉,
	commission_pct, salary * (1 + ifnull(commission_pct, 0)) *12 "커미션포함 연봉"
from employees;

 

4. NULLIF()

  • NULLIF(expr1, expr2)
  • expr1과 expr2의 값이 서로 같으면 NULL 반환, 같지 않으면 expr1 반환

 

패턴 매칭

1. LIKE 

  • 원하는 패턴의 문자열 검색
  • % : sub string (0개 이상)
  • _ : 한 글자

* `like`를 `=`으로 사용하지 않도록 주의 

-- 이름에 'x'가 들어간 사원의 사번, 이름
select employee_id, first_name
from employees
where first_name like '%x%'; 
-- where first_name = '%x%'; # '=' 불가!!!!

-- 이름의 끝에서 3번째 자리에 'x'가 들어간 사원의 사번, 이름
select employee_id, first_name
from employees
where first_name like '%x__';

 

2. REGEXP

  • LIKE 보다, 더 복잡한 패턴을 검색하는 경우
 패턴   설명
. 줄 바꿈 문자(\n)를 제외한 임의의 한 문자
* 해당 문자 패턴이 0번 이상 반복
+ 해당 문자 패턴이 1번 이상 반복
^ 문자열의 처음
$ 문자열의 끝
| 선택 (OR)
[...] 괄호([]) 안에 있는 어떠한 문자
[^...] 괄호([]) 안에 있지 않은 어떠한 문자
{n} 반복되는 횟수 지정
{m,n} 반복되는 횟수의 최솟값과 최댓값 지정
-- 홍'으로 시작하거나, '산'으로 끝나는 이름
SELECT * FROM Reservation
WHERE Name REGEXP '^홍|산$';

 

 

타입 변환

1. BINARY

  • 연산자 뒤에 오는 문자열을 바이너리 문자열로 변환
SELECT BINARY 'a' = 'A'; -- false
SELECT 'a' = 'A'; -- true

 

2. CAST()

  • 수로 전달받은 값을 명시된 타입으로 변환
  • 변환하고자 하는 타입을 AS 절을 이용하여 명시
  • CAST(expr AS type)
select cast(1 as char) as "cast 문자",
       cast('23' as signed) as "cast 숫자",
       cast('20230822' as date) as "cast 날짜";

 

3. CONVERT()

  • CAST() 함수처럼 인수로 전달받은 값을 명시된 타입으로 변환하여 반환
  • CONVERT(expr, type)
SELECT CONVERT(20230822, DATE);

 

 

다중 테이블 연산

1. JOIN

: 데이터베이스 내의 여러 테이블에서 가져온 레코드를 조합하여 하나의 테이블이나 결과 집합으로 표현해 줌

 

      1) INNER JOIN 

          - 단순히 from 절에 `,`를 사용하는 경우, inner join 으로 연산

          - ON 절과 함께 사용되며, ON 절의 조건을 만족하는 데이터만 가져옴

          - 표준 SQL과는 달리 MySQL에서는 JOIN, INNER JOIN, CROSS JOIN이 모두 같은 의미로 사용됨

          - 테이블1 INNER JOIN(JOIN) 테이블2 ON 조건

SELECT * FROM TableA A JOIN TableB B ON A.key = B.key;

 

      2) LEFT JOIN

          - 첫 번째 테이블을 기준으로, 두 번째 테이블을 조합하는 JOIN

          - ON 절의 조건을 만족하지 않는 경우에는 첫 번째 테이블의 필드 값은 그대로 가져옴

            but, 해당 레코드의 두 번째 테이블의 필드 값은 모두 NULL로 표시

          - 테이블1 LEFT JOIN 테이블2 ON 조건

-- LEFT OUTER JOIN
SELECT * FROM TableA A LEFT JOIN TableB B ON A.key = B.key;

-- 순수 A만 구할 때
SELECT * FROM TableA A LEFT JOIN TableB B ON A.key = B.key
WHERE B.Key IS NULL;

 

      3) RIGHT JOIN

          - 두 번째 테이블을 기준으로, 첫 번째 테이블을 조합하는 JOIN

          - ON 절의 조건을 만족하지 않는 경우에는 두 번째 테이블의 필드 값은 그대로 가져옴

             but, 해당 레코드의 첫 번째 테이블의 필드 값은 모두 NULL로 표시

          - 테이블1 RIGHT JOIN 테이블2 ON 조건

 

-- RIGHT OUTER JOIN
SELECT * FROM TableA A RIGHT JOIN TableB B ON A.key = B.key;

-- 순수 B만 구할 때
SELECT * FROM TableA A RIGHT JOIN TableB B ON A.key = B.key
WHERE A.Key IS NULL;

 

      4) FULL OUTER JOIN

       - MySQL은 FULL OUTER JOIN이 없지만, LEFT JOIN 과 RIGHT JOIN을 이용해 FULL OUTER JOIN 사용 가능

 

SELECT * FROM TableA A LEFT JOIN TableB B 
UNION
SELECT * FROM TableA A RIGHT JOIN TableB B

-- 교집합 제외
SELECT * FROM TableA A LEFT JOIN TableB B 
UNION
SELECT * FROM TableA A RIGHT JOIN TableB B
WHERE A.key IS NULL OR B.key IS NULL

 

2. UNION

  • 여러 개의 SELECT 문의 결과를 하나의 테이블이나 결과 집합으로 표현할 때 사용
  • SELECT 필드이름 FROM 테이블이름 UNION SELECT 필드이름 FROM 테이블이름

          -  DISTINCT 키워드를 따로 명시하지 않아도 기본적으로 중복되는 레코드를 제거

          - 중복되는 레코드까지 모두 출력하고 싶다면, `ALL` 키워드를 사용

              SELECT 필드이름 FROM 테이블이름 UNION ALL SELECT 필드이름 FROM 테이블이름

 

SELECT Name
FROM Reservation
UNION -- UNION ALL 
SELECT Name
FROM Customer;

 

3. 서브 쿼리

  • 다른 쿼리 내부에 포함되어 있는 SELETE 문
  • 서브쿼리를 포함하고 있는 쿼리 = 외부쿼리(outer query) / 서브쿼리 = 내부쿼리(inner query)
  • 서브쿼리는 반드시 괄호(())로 감싸져 있어야 함

 

profile

danbibibi

@danbibibi

꿈을 꾸는 시간은 멈춰 있는 것이 아냐 두려워하지 마 멈추지 마 푸른 꿈속으로