<<include>>와 <<extend>>의 자세한 쓰임을 배웠다. <<include>>는 특정 유스케이스를 실행하기 위해 반드시 먼저 수행되어야 하는 필수 관계를 나타내고, <<extend>>는 특정 조건 하에서만 선택적으로 실행할 수 있는 확장 기능을 나타낸다.
또한, Single Responsibility Principle(SRP)를 근거로 하나의 유스케이스에서는 하나의 기능만 작동해야 함을 강조해야한다.

이처럼 입금과 출금 두개의 기능이 있음에도 '입출금'으로 묶는 건 해당 원칙에 위반된다.


MariaDB나 MySQL을 다뤄본적은 없기에 미숙하였지만 설치법부터 사용법까지 상세히 알려주어서 지금은 원하는대로 쿼리를 잘 짤 수 있게 되었다. CREATE USER 'swcamp'@'%' IDENTIFIED BY 'swcamp';) 스크립트 파일로 저장하여 복습하기에 좋았다.ACID 트랜잭션 원칙에 대해서 개념을 상기하게 되었다.
Atomicity(원자성)은 모든 작업이 전부 성공하거나 전부 실패함을 뜻한다. 은행으로 예시를 들자면, 백만 원을 출금해서 완료 메시지가 떴지만 기기에서 출금이 되지 않을 때 다시 출금 이전으로 돌아가야한다. 이처럼 단위별로 연산을 하여 모든 작업이 성공적으로 연산이 되면 반영이 됨을 뜻한다. Consistency(일관성)은 트랜잭션이 성공적으로 완료된 후에도 데이터베이스가 항상 일관된 상태를 유지해야 함을 뜻한다. 방금 전 백만 원 출금 전으로 돌아갔다면, 데이터베이스에는 여전히 백만 원이 반영되어 있어야 한다.Isolation(고립성)은 여러 트랜잭션이 동시에 실행될 때, 각 트랜잭션이 서로에게 영향을 주지 않고 독립적으로 실행되는 것을 보장함을 의미한다. A가 계좌에서 10만원을 뺀다고 했을 때, 그 연산이 이루어지는 순간에 계좌조회나 송금 연산은 막아주어야 한다.Durability(지속성)은 트랜잭션의 결과는 시스템에 장애가 발생하더라도 영구적으로 저장되고 손실되지 않아야 한다는 원칙이다. 커밋이 완료 되면 그 변경 사항은 불변해야 하며 변경 사항을 볼 수 있게 해야한다.CREATE USER 'swcamp'@'%' IDENTIFIED BY 'swcamp';는 새로운 사용자를 생성하겠다는 명령어인 CREATE USER로 시작되어, swcamp는 그 사용자의 ID이며, @는 접속 위치인 호스트를 가리키고, %는 모든 곳에서 접속을 허용한다는 의미이다. (192.0.0.1이나 localhost 등 옵션이 다양) 그리고 IDENTIFIED BY 'swcamp';는 비밀번호를 swcamp로 설정한다는 의미이다.
GRANT ALL PRIVILEGES ON menudb.* TO 'swcamp'@'%';에서 GRANT ON TO 구문은 알고 있었지만 ALL PRIVILEGES에 대해 새롭게 알게 되었다. SELECT, INSERT, UPDATE, DELETE, CREATE, DROP 등의 모든 권한을 부여함과 같은 의미이다. 그리고 'swcamp'@'%'; 역시 모든 위치에서 접속하는 swcamp 사용자에게 권한을 부여한다는 의미이다.
DBeaver에서 쿼리를 드래그한 뒤Alt+x로 스크립트 모드에 진입 후 실행하면 한번에 모든 쿼리가 실행이 된다.
SELECT문은 기본적으로 SELECT FROM의 형식을 따른다.
select 7 + 3;을 사용 가능, select now() as '현재 시간'; 이나 select now() as "현재 시간"; 처럼 as로 컬럼의 이름을 설정할 수도 있다. ORDERBY문은 기본적으로 SELECT FROM 후에 후순위에 사용된다. order by 후에 컬럼을 정렬하고 그 정렬된 순서에서 중복된 값이 있다면 추가적으로 컬럼을 정렬할 수도 있다.
select
menu_code
, menu_name
, menu_price
from tbl_menu
order by menu_price desc, menu_code;
SELECT 구문이나 GROUPBY 구문은 익혔지만, 여전히 초기 설정(계정 설정, 권한 부여)에 대해는 모호하기 때문에 여러 계정을 만들고 계정마다 데이터베이스를 꾸리는 연습을 하고싶다.ORDER BY, WHERE, DISTINCT, LIMIT을 배웠는데, 그동안 이론으로만 알고 있었던 내용들을 실제로 실습하면서 다시 깨우치니 이해가 빨랐다.WHERE, ORDER BY 등의 위치 등) 내용들을 바로잡을 수 있었다. field는 첫번째 인자가 몇 번째에 있는지 알려주는 쿼리문이다. select field('A', 'A', 'B', 'C'); 는 1이 반환된다. 
tbl_category에서 category_code에서 null이면 그것이 최상위이다. 그리고 그 최상위를 참조하는 행이 있다. 
from, 2. select, 3. order by였다면 where절에서는 순서가 사진 처럼 진행된다. 2번을 거쳐 3번으로 갈 때는 SELECT된 내용을 전달하는 것이 아닌 컬럼 전체 내용을 들고 간다. 아래는 기본 순서이다. SELECT
컬럼명
, 컬럼명
... (3)
FROM 테이블명 (1)
WHERE 컬럼명(조건식) 값 (2)
ORDER BY 컬럼명 asc(desc), ...; (4)
SELECT
*
FROM tbl_menu
WHERE category_code = 4
OR menu_price = 9000
AND menu_code > 10;
먼저 menu_price = 9000와 menu_code > 10 인 것을 먼저 찾는다. 그 and 결과와 category_code=4를 OR 연산하여 결과를 도출한다.
즉, AND 조건 처리는 menu_price가 9000이면서 menu_code가 10을 초과하는 모든 메뉴를 먼저 찾고, OR 조건 처리는 그 결과에 category_code가 4인 모든 메뉴를 추가로 포함하여 최종 결과를 보여준다.
distinct는 중복된 내용이 없게끔 뽑겠다는 의미이고 뒤에 오면 안되고, 맨 앞에 와야한다.


이 테이블에 SELECT DISTINCT category_code, orderable_status FROM tbl_menu; 쿼리를 실행하면, 시스템은 (category_code, orderable_status) 조합의 중복을 찾는다.

LIMIT는 정렬된 결과로부터 첫번째 인덱스에서 숫자만큼 보여주는 쿼리이다.
SELECT
menu_code
, menu_name
, menu_price
FROM tbl_menu
ORDER BY menu_price
LIMIT 1, 4;
이는 첫번째 인덱스(실제로는 두번째에 위치한 값)에서 4개까지 보여준다. 결과는 4개가 나오게 된다.
>>>> 무슨계정에서 실행(root)
root
mariadb1 >>> use mysql
1. 데이터베이스 생성
데이터베이스명 : ott_platform
create database ott_platform;
2. 계정 생성 :
아이디 : 'ott_admin'@'%'
비밀번호 : admin
create user 'ott_admin'@'%' identified by 'admin';
3. 권한 전부 제공
grant all privileges on ott_platform.* to 'ott_admin'@'%';
github의 학습이 다소 미흡하다는 것의 방증이라고 생각한다. github 포크나 PR 관련 수업 자료들을 찾아보고 혼자서 계정을 만들어 PR하는 연습을 해보고싶다는 생각을 하였다.모든 테이블에는 식별자인 주키(#)가 있다. 누군가가 그 주키를 참조를 하면 외래 식별자이다.

이 사진처럼 복합되면, 고객이 상품을 일대다로 담을 수 있는 관계가 된다.
JOIN을 할 때 USING과 ON의 차이점을 알게 되었다. ON을 사용할 때는 a.category_code = b.category_code처럼 조인할 컬럼을 직접 지정한다. 이처럼 두 컬럼의 이름이 달라도 사용할 수 있다. USING(category_code)를 사용하면 조인할 컬럼의 이름이 두 테이블에서 모두 같을 때만 사용할 수 있다.
INNER JOIN과 LEFT(RIGHT) JOIN를 사용하여 쿼리문을 직접 써보는 실습을 하였다.
INNER JOIN은 교집합으로 두 테이블에 모두 존재하는 데이터, 즉 짝이 맞는 데이터만 보여준다. 이는 실제로 주문한 고객의 정보를 찾거나 댓글이 달린 동영상만 보고 싶을 때 사용한다. 양쪽 테이블에 모두 정보가 있는 확실한 데이터만 필요할 때 사용한다. LEFT(RIGHT) JOIN은 왼쪽 혹은 오른쪽 테이블의 모든 데이터를 기준으로 그 반대편의 데이터를 찾아와 붙인다. 주로 모든 고객 목록을 보고 고객이 주문을 했는지 안 했는지, 동영상 목록에서 댓글이 없는 게시글도 보고 싶을 때 사용한다. 짝이 없는 데이터는 NULL로 표시된다.SELECT
a.emp_name
, b.DEPT_TITLE
, c.JOB_NAME
FROM employee a
LEFT JOIN department b ON a.DEPT_CODE = b.DEPT_ID
JOIN job c ON a.JOB_CODE = c.JOB_CODE;
이 쿼리에서 기준이 되는 베이스테이블은 employee 테이블이다.
CROSS JOIN은 두 테이블의 모든 가능한 조합을 반환하는 JOIN이다. 첫번째 테이블의 행 개수와 두 번째 테이블의 행 개수를 곱한 조합이 결과로 나온다. ON이나 USING 과 같은 연결조건이 필요 없다.
SELF JOIN은 하나의 테이블에 두 개의 다른 별명을 부여해서 마치 서로 다른 두 개의 테이블인 것처럼 다루는 것이다.
SELECT
a.emp_name 사원명
, b.emp_name 관리자명
FROM employee a
JOIN employee b ON a.MANAGER_ID = b.EMP_ID;
LEFT JOIN 문제를 풀었을 때 INNER JOIN과 혼동하였다. 그래서 처음에는 조금 버벅였다. WHERE
category_code = (SELECT category_code
FROM tbl_menu
WHERE menu_name = '민트미역국'
);
이는 결과가 하나이기 때문에 다른 연산자가 필요 없지만,
WHERE
category_code IN (SELECT category_code
FROM tbl_category
WHERE ref_category_code = 1
);
ref_category_code가 가리키는 category_code는 4개 나오므로 IN, NOT IN, ANY, ALL의 연산자가 필요하다.
IN의 기본 사용법은 OR을 반복해서 써야하는 것을 대체하는 것이라고 배웠다. 그러나 IN의 진짜 힘은 서브쿼리와의 조합에서 드러난다. 만약 '식사' 카테고리의 코드를 찾는다면, ref_category_code를 찾아야 한다. SELECT
menu_name
FROM tbl_menu
WHERE category_code IN (SELECT category_code
FROM tbl_category
WHERE ref_category_code = 1);
처럼 IN은 정적인 값 목록을 비교하는 용도를 넘어서 WHERE절의 조건으로 사용된다. 이 때, WHERE category_code IN (SELECT category_code .... 처럼 IN 앞의 컬럼과 서브쿼리 SELECT 뒤에 오는 컬럼은 서로 비교할 대상이기 때문에 같은 종류의 데이터여야 한다. 즉, 논리적으로 의미가 연결 되어야 한다 (이름은 다를지언정)
EXISTS는 '하나라도 있는 것을 뽑아줘' 처럼 존재여부를 확인해주는 서브쿼리이다.SELECT
a.category_name, a.category_code
FROM
tbl_category a
WHERE EXISTS (SELECT 1 -- 행이 존재하냐?의 의미의 1
FROM tbl_menu b
WHERE b.category_code = a.category_code
);
이 코드에서, 바깥쿼리가 카테고리를 선택하고 서브쿼르가 실행된다. tbl_menu의 카테고리 코드가 tbl_category의 카테고리 코드 (4부터 시작 됨)와 동일한지 tbl_menu 안에서 찾는다. 한 건이라도 찾으면 즉시 TRUE를 반환하고 4를 결과에 포함시킨다.
SELECT
a.menu_name
, (SELECT b.category_name
FROM tbl_category b
WHERE b.category_code = a.category_code
) category_name
FROM tbl_menu a
결과값이 단일값 (1개의 행이나 1개의 열)인 상관 서브쿼리의 한 종류이다. 주로 SELECT절이나 WHERE절에 위치한다.
FROM절에 위치한 서브쿼리로, 인라인 뷰라고도 하는 것을 배웠다. SELECT -- 인라인뷰에 존재하는 컬럼만 참조할 수 있다.
v.menu_name
, v.category_name
, v.menu_price
FROM (SELECT a.menu_name
, (SELECT category_name
FROM tbl_category b
WHERE b.category_code = a.category_code
) category_name
, a.menu_price
FROM tbl_menu a
) v -- 별칭을 붙여줘야함
인라인 뷰는 반드시 가상 테이블에 별칭을 붙여줘야한다.
tbl_menu 테이블의 각 메뉴에 대해 SELECT절 안의 스칼라 서브쿼리가 실행된다. (순서가 FROM -> SELECT이기 때문) 이 스칼라 서브쿼리는 해당 메뉴의 category_code와 일치하는 category_name을 tbl_category에서 찾아와 붙여준다 (JOIN과 비슷할듯) 결과적으로 menu_name, category_name, menu_price 컬럼을 가진 테이블 v가 만들어진다. 이제 이 v를 실제 테이블처럼 사용하여 최종 결과를 조회한다.
많은 종류의 서브쿼리를 한번에 배우다보니 각자의 쓰임새와 문법에 대해 많이 헷갈리는 부분들이 있었다. 스칼라 서브쿼리와 인라인뷰를 합쳐서 사용하는 서브쿼리는 복잡하여 이해하는 데에 시간이 걸렸던 것 같다.
서브쿼리의 양이 많아지다보니 순서 매커니즘을 잊고 무작정 쿼리를 작성하는 데에 급급했던 것 같다.
문제를 풀 때 주제 : 인라인 뷰를 사용하여.. 등 어떻게 하라는 지시가 있어서 감이 잡혔지만, 그런 주제들이 주어지지 않고 문제만 보고 풀었다면 더욱 헷갈렸을 것 같다. 그래서 단순히 문제만 보고 어떤 서브쿼리를 대입하여 풀어야하는지 많은 연습을 해야겠다고 생각했다.
프로그램이 순서를 읽는 기초부터 다시 천천히 공부하고 그 순서에 따라서 천천히 문제를 해석하고 풀어야겠다는 생각이 들었다