0118

BE

[혼자공부하는SQL] Summary2

9강

1. 데이터 형식

1) 정수형

(1) 종류

데이터 형식

바이트 수

TINYINT

1 (-128 ~ 127)

SMALLINT

2 (-32,768 ~ 32,767)

INT

4 (약 -21억 ~ + 21억)

BIGINT

8 (약 -900경 ~ + 900경)

(2) UNSIGNED

: 값의 범위가 0부터 시작되고, 음수까지의 범위가 양수로 더해진다.

  • ex) TINYINT UNSIGNED → (0 ~ 256)

2) 문자형

(1) 종류

데이터 형식

바이트 수

특징

CHAR(개수)

1~255

고정형 문자형

VARCHAR(개수)

1~16383

가변형 문자형

- BINARY, VARBINARY도 있지만, 잘 사용하지 않는다.

(2) 고정형 문자형인 CHAR의 공간 낭비

: CHAR는 글자의 개수가 고정된 경우, VARCHAR는 글자의 개수가 변동될 경우에 사용하는 것이 좋다.

(3) 숫자로서 의미를 가지려면 아래의 두 가지 중 하나는 충족해야 한다.

  • 더하기/빼기 등의 연산에 의미가 있어야 한다.

  • 크다/작다 또는 순서에 의미가 있어야 한다.

3) 대량의 데이터 형식

(1) 종류

데이터 형식

바이트 수

특징

TEXT

1~65535

LONGTEXT

1~4394967295 (최대 4GB)

대량의 텍스트에 사용

BLOB

1~65535

LONGBLOB

1~4394967295 (최대 4GB)

대량의 이진 데이터에 사용

- TINYTEXT, MEDIUMTEXT, TINYBLOG, MEDIUMBLOB도 있지만, 잘 사용하지 않는다.

4) 실수형

(1) 종류

데이터 형식

바이트 수

설명

FLOAT

4

소수점 아래 7자리까지 표현

DOUBLE

8

소수점 아래 15자리까지 표현

- 과학 기술용 데이터가 아닌 이상 FLOAT이면 충분하다.

- 정밀성의 차이다

5) 날짜형

(1) 종류

데이터 형식

바이트 수

설명

DATE

3

날짜만 저장, YYYY-MM-DD 형식으로 사용

TIME

3

시간만 저장, HH:MM:SS 형식으로 저장

DATETIME

8

날짜 및 시간을 저장, YYYY-MM-DD HH:MM:SS 형식으로 저장

- 내부적으로 데이터양이 다르기 때문에, 필요에 따라 적절한 데이터 형식을 사용하는 것이 중요하다.

2. 변수의 사용

1) 선언 및 대입

SQL
-- 변수의 선언 및 값 대입
SET @변수이름 = 변수의 값

2) 출력

SQL
-- 변수의 값 출력
SELECT @변수이름;

3) PREPARE / EXECUTE

(1) 의미

: SQL에서 동적 쿼리를 실행하기 위한 기능으로, 먼저 쿼리를 준비(PREPARE)한 후 실행(EXECUTE)할 수 있도록 한다. 이를 통해 동일한 쿼리를 반복 실행할 때 성능을 최적화하고 SQL 인젝션을 방지할 수 있다.

(2) 형식

SQL
SET @count = 3;
PREPARE mySQL FROM 'SELECT mem_name, height FROm member ORDER BY height LIMIT ?';
EXECUTE mySQL USING @count;
  • 변수를 물음표(?)를 사용하여 지정하고, 필요할 때 EXECUTE로 사용하고 USING으로 변수를 할당한다.

3. 데이터 형 변환

1) 의미

: 문자형을 정수형으로 바꾸거나, 정수형을 문자형으로 바꾸는 것

2) 종류

  • 명시적인 변환(explicit conversion) : 직접 함수를 사용해서 변환하는 방법

  • 암시적인 변환(implicit conversion) : 별도의 지시 없이 자연스럽게 변환되는 방법

3) 명시적인 변환

(1) 데이터 형식을 변환하는 함수

  • 종류

    • CAST()

    • CONVERT()

  • 형식

  • CAST (값 AS 데이터_형식 [(길이)] ) CONVERT (값, 데이터_형식 [(길이)] )

4) 암시적인 형 변환

(1) 예시

SQL
-- 문자와 문자를 더함 (정수로 변환되어 연산됨) → 결과: 300  
SELECT '100' + '200';  

-- 문자와 문자를 연결 (문자로 처리) → 결과: '100200'  
SELECT CONCAT('100', '200');  

-- 정수와 문자를 연결 (정수가 문자로 변환되어 처리) → 결과: '100200'  
SELECT CONCAT(100, '200');  

-- '2mega'가 정수 2로 변환되어 비교 → 결과: FALSE (1 > 2 → FALSE)  
SELECT 1 > '2mega';  

-- '2MEGA'가 정수 2로 변환되어 비교 → 결과: TRUE (3 > 2 → TRUE)  
SELECT 3 > '2MEGA';  

-- 'mega2'가 0으로 변환되어 비교 → 결과: TRUE (0 = 0 → TRUE)  
SELECT 0 = 'mega2';

10강

0. 개요

1) 조인 (join)

: 두 개의 테이블을 서로 묶어서 하나의 결과를 만들어내는 것

1. 내부 조인

: 조인이라 부르면, 내부 조인을 의미한다.

1) 형식

SQL
SELECT <열 목록>
FROM <첫 번째 테이블>
    INNER JOIN <두 번째 테이블>
    ON <조인될 조건>
[WHERE 검색 조건]
  • INNER JOIN을 JOIN이라고만 써도 INNER JOIN으로 인식한다.

2) 특정 열에 대한 지정

SQL
-- 오류 발생
SELECT mem_id, mem_name, prod_name, addr, CONCAT(phone1, phone2) AS '연락처'
FROM buy
    INNER JOIN member
    ON buy.mem_id = member.mem_id;
-- 해결
SELECT buy.mem_id, mem_name, prod_name, addr, CONCAT(phone1, phone2) AS '연락처'
FROM buy
    INNER JOIN member
    ON buy.mem_id = member.mem_id;

3) 테이블의 별칭

code
SELECT B.mem_id, M.mem_name, B.prod_name, M.addr, CONCAT(M.phone1, M.phone2) AS '연락처'
FROM buy B
    INNER JOIN member M
    ON B.mem_id = M.mem_id;

4) 내부 조인의 한계

: 구매한 사람들만 나왔다. 구매하지 않은 경우도 봐야 하는데 말이다. 구매 안 했으면 구매한 적 없다고 해야 하지 않을까? → 이것이 바로 외부 조인

5) 기본키 / 외래키

  • 기본키 (Primary key)

  • 외래키 (Foreign key)

2. 외부 조인 (Outer JOIN)

  • 내부 조인은 두 테이블에 모두 데이터가 있어야만 결과가 나온다.

  • 하지만, 외부 조인은 한 쪽에만 데이터가 있어도 결과가 나온다.

  • 외부 조인은 두 테이블을 조인할 때 필요한 내용이 한쪽 테이블에만 있어도 결과를 추출할 수 있다.

1) 형식

SQL
SELECT <열 목록>
FROM <첫 번째 테이블(LEFT 테이블)>
    <LEFT | RIGHT | FULL> OUTER JOIN <두 번째 테이블(RIGHT 테이블)>
    ON <조인될 조건>
[WHERE 검색 조건]

(1) LEFT OUTER JOIN

  • 왼쪽 테이블의 모든 행을 포함하며, 오른쪽 테이블에 일치하는 값이 없으면 NULL을 반환한다.

(2) RIGHT OUTER JOIN

  • 오른쪽 테이블의 모든 행을 포함하며, 왼쪽 테이블에 일치하는 값이 없으면 NULL을 반환한다.

(3) FULL OUTER JOIN

  • 왼쪽 외부 요인과 오른쪽 외부 조인이 합쳐진 것

  • 왼쪽이든 오른쪽이든 한 쪽에 들어 있는 내용이면 출력한다.

3. 기타 조인

1) 상호 조인 (CROSS JOIN)

  • 한쪽 테이블의 모든 행과 다른 쪽 테이블의 모든 행을 조인시키는 기능

  • 그래서 상호 조인 결과의 전체 행 개수는 두 테이블의 각 행의 개수를 곱한 개수가 된다.

  • 카티션 곱(cartesian product)이라고도 부른다.

(1) 형식

SQL
SELECT *
FROM 테이블
CROSS JOIN 테이블;

(2) 특징

  • ON 구문을 사용할 수 없다.

  • 결과의 내용은 의미가 없다. 랜덤으로 조인하기 때문이다.

  • 상호 조인의 주 용도는 테스트하기 위해 대용량의 데이터를 생성할 때이다.

2) 자체 조인 (Self JOIN)

  • 자체조인은 자신이 자신과 조인한다는 의미이다.

  • 그래서 자체 조인은 1개의 테이블을 사용한다.

  • 별도의 문법이 있는 것은 아니고, 1개로 조인하면 자체 조인이 된다.

(1) 형식

SQL
SELECT <열 목록>
FROM <테이블> 별칭A
    INNER JOIN <테이블> 별칭 B
    ON <조인될 조건>
[WHERE 검색 조건]

11강

0. 개요

1) 스토어드 프로시저

(1) 의미

: MySQL에서 프로그래밍 기능이 필요할 때 사용하는 데이터베이스 개체이다.

: SQL 프로그래밍은 기본적으로 스토어드 프로시저 안에 만들어야 한다.

(2) 구조

code
DELIMITER $$ -- 스토어드 프로시저의 코딩 부분
CREATE PROCEDURE 스토어드_프로시저_이름()
BEGIN
-- 이 부분에 SQL 프로그래밍 코딩
END $$ -- 스토어드 프로시저 종료
DELIMITER; -- 종료 문자를 다시 세미콜론(;)으로 변경

CALL 스토어드_프로시저_이름(); -- 스토어드 프로시저 실행
  • 일반적으로 구분문자(DELIMITER)는 $$를 많이 사용하지만, 원한다면 /, &, Q 등을 사용해도 상관없다. 다른 기호와 중복될 수 있으므로, 기호 2개를 연속해서 사용하는 것이 좋다.

  • 즉, 스토어드 프로시저는 DEIMITER $$ ~ END $$ 안에 작성하고 CALL로 호출한다.

1. IF문

: 조건문으로 가장 많이 사용되는 프로그래밍 문법 중 하나이다.

1) IF 문의 기본 형식

: IF문은 조건식이 참이라면 ‘SQL문장들’을 실행하고, 그렇지 않으면 그냥 넘어간다.

(1) 형식

SQL
IF <조건식> THEN
    SQL문장들
END IF;

: ‘SQL문장들’이 한 문장이라면, 그 문장만 써도 되지만, 두 문장 이상이 처리되어야 할 때는 BEGIN ~ END로 묶어줘야 한다.

2) IF ~ ELSE문

: 조건에 따라 다른 부분을 수행한다. 조건식이 참이라면 ‘SQL문장1’을 실행하고, 그렇지 않으면 ‘SQL문장2’를 실행한다.

(1) 형식

SQL
-- 한 번만 사용한 경우
IF <조건식> THEN
    SQL문장들
ELSE
    SQL문장들
END IF;

-- 두 번 이상 사용한 경우
IF <조건식> THEN
    SQL문장들
ELSEIF
    SQL문장들
ELSEIF
    SQL문장들    
ELSE
    SQL문장들
END IF;

3) 응용

(1) 변수 선언

SQL
DECLARE 변수명 변수타입;

(2) 검색 결과를 변수에 저장

SQL
SELECT 열_이름 INTO 저장할 변수
    FROM 테이블
    WHERE 조건

(3) 현재 날짜 구하는 함수 : CURRENT_DATE();

SQL
-- 예시
SET curDATE = CURRENT_DATE()

(4) 날짜의 차이 (일 단위)를 구하는 함수 : DATEDIFF(최근 날짜, 데뷔 날짜)

SQL
-- 특징 : 결과가 양수면 날짜1이 더 미래, 음수면 날짜2가 더 미래이다.
SELECT DATEDIFF('2025-12-31', '2025-01-01') AS result; -- 결과: 364 (날짜 차이)  
SELECT DATEDIFF('2025-01-01', '2025-12-31') AS result; -- 결과: -364  
SELECT DATEDIFF(NOW(), '2024-01-01') AS result; -- 현재 날짜와 비교 가능

2. CASE문

: 조건을 설정하여 여러 가지 조건 중 선택할 수 있다.

1) CASE문의 기본 형식

: IF문은 참 아니면 거짓 두 가지만 있기 때문에, 2중 분기라는 용어를 사용한다.

: 반면, CASE문은 2가지 이상의 여러 가지 경우일 때 처리가 가능하므로 다중 분기라고 부른다.

: SWITCH ~ CASE문과 비슷한 기능을 한다.

(1) 형식

SQL
CASE
    WHEN 조건1 THEN
        SQL문장들1
    WHEN 조건2 THEN
        SQL문장들2
    WHEN 조건3 THEN
        SQL문장들3
    ELSE
        SQL문장들4
END CASE;

: 조건이 여러개라면 WHEN을 여러 번 반복하고, 모든 조건에 해당하지 않으면 마지막 ESLE 부분을 수행한다.

2) CASE 문의 활용

(1) 예시의 상황

: 회원의 등급을 4단계로 나누려고 한다.

총 구매액

회원등급

1500 이상

최우수고객

1000 ~ 1499

우수 고객

1~999

일반고객

0 이하 (구매한 적 없음)

유령 고객

(2) 코드

SQL
USE market_db;

-- 그룹 별 총 구매액
SELECT mem_id, SUM(price * amount)
    FROM buy
    GROUP BY mem_id;

-- 그룹 별 총 구매액 (내림차순)
SELECT mem_id, SUM(price * amount)
    FROM buy
    GROUP BY mem_id
    ORDER BY SUM(price * amount) DESC;

-- 그룹 별 총 구매액 (내림차순) - 아이디, 이름, 구매액
SELECT B.mem_id, M.mem_name, SUM(price * amount)
    FROM buy B
        INNER JOIN member M
        ON B.mem_id = M.mem_id
    GROUP BY B.mem_id
    ORDER BY SUM(B.price * B.amount) DESC;

-- 그룹 별 총 구매액 (내림차순) - 유령 고객까지 반영 (mem_id를 신경 쓰기)
SELECT M.mem_id, M.mem_name, SUM(price * amount)
    FROM buy B
        RIGHT OUTER JOIN member M
        ON B.mem_id = M.mem_id
    GROUP BY M.mem_id
    ORDER BY SUM(B.price * B.amount) DESC;

-- 그룹 별 총 구매액 (내림차순) - CASE 적용
SELECT M.mem_id, M.mem_name, SUM(price * amount),
        CASE
            WHEN (SUM(price * amount) >= 1500) THEN '최우수고객'
            WHEN (SUM(price * amount) >= 1000) THEN '우수고객'
            WHEN (SUM(price * amount) >= 1) THEN '일반고객'
            ELSE '유령고객'
        END "회원등급"
    FROM buy B
        RIGHT OUTER JOIN member M
        ON B.mem_id = M.mem_id
    GROUP BY M.mem_id
    ORDER BY SUM(B.price * B.amount) DESC;

(3) 궁금증

Q. 예시 1에서는 CASE 뒤에 END 하고 CASE 라고 적었는데, 예시 2에서는 END 하고 "회원등급"이라고 했어. 무슨 차이고 왜 그런거야?

  • 상황

    SQL
      DROP PROCEDURE IF EXISTS caseProc;
      DELIMITER $$
      CREATE PROCEDURE caseProc()
      BEGIN
      -- 변수 선언
      DECLARE point INT ;
      DECLARE credit CHAR(1);
    
      -- 점수 가정 (대입)
      SET point = 88 ;
    
      CASE
          WHEN point >= 90 THEN
              SET credit = 'A';
          WHEN point >= 80 THEN
              SET credit = 'B';
          WHEN point >= 70 THEN
              SET credit = 'C';
          WHEN point >= 60 THEN
              SET credit = 'D';
          ELSE
              SET credit = 'F';
      END CASE;
    
      SELECT CONCAT('취득점수==>', point), CONCAT('학점==>', credit);
    
      END $$
      DELIMITER ;
      CALL caseProc();

    예시2

  • SELECT M.mem_id, M.mem_name, SUM(price * amount), CASE WHEN (SUM(price * amount) >= 1500) THEN '최우수고객' WHEN (SUM(price * amount) >= 1000) THEN '우수고객' WHEN (SUM(price * amount) >= 1) THEN '일반고객' ELSE '유령고객' END "회원등급" FROM buy B RIGHT OUTER JOIN member M ON B.mem_id = M.mem_id GROUP BY M.mem_id ORDER BY SUM(B.price * B.amount) DESC;

  • 예시 1

A. CASE 문은 프로시저 내부에서 변수에 값을 할당할 때와 SELECT 문에서 컬럼 값을 결정할 때 사용하는 방식이 다르다.

구분

사용 위치

END 뒤 표현

설명

예시 1

프로시저 내부 (SET 사용)

END CASE;

CASE 문이 단독으로 사용되며, SET을 통해 변수에 값을 할당하기 때문에 END CASE;로 종료해야 한다.

예시 2

SELECT 문 내부 (컬럼 값 결정)

"회원등급"

CASE 문이 SELECT 문의 컬럼 값으로 사용되므로, END 뒤에 컬럼명을 지정하여 결과 테이블에 해당 값이 포함되도록 해야 한다.

즉, 예시 1에서는 프로시저 내부에서 값 할당을 위해 END CASE;로 종료하고, 예시 2에서는 SELECT 문에서 컬럼 값을 결정하므로 END 뒤에 컬럼명을 명시한 것이다.

3. WHILE문

1) WHILE문의 기본 형식

: WHILE문은 조건식이 참인 동안에 SQL문장들을 계속 반복한다.

(1) 형식

SQL
WHILE <조건식> DO
    SQL 문장들
END WHILE;

2) WHILE문의 응용

(1) 종류

  • ITERATE [레이블] : 지정한 레이블로 가서 계속 진행한다.

  • LEAVE [레이블] : 지정한 레이블을 빠져나간다. 즉 WHILE문이 종료된다.

(2) 예시

code
DROP PROCEDURE IF EXISTS whileProc2;
DELIMITER $$
CREATE PROCEDURE whileProc2()
BEGIN
    -- 변수 선언
    DECLARE i INT; -- 1에서 100까지 증가할 변수
    DECLARE hap INT; -- 더한 값을 누적할 변수

    -- 변수 대입
    SET i = 1;
    SET hap = 0;

    myWhile: -- While문에 label을 지정
    WHILE (i <= 100) DO
       IF (i%4 = 0) THEN -- 생략 조건
         SET i = i + 1;
         ITERATE myWhile; -- 지정한 label문으로 가서 계속 진행
       END IF;

       SET hap = hap + i;

       IF (hap > 1000) THEN -- 종료 조건
         LEAVE myWhile; -- 지정한 label문을 떠남. 즉, While 종료.
       END IF;

       SET i = i + 1;
    END WHILE;

    SELECT '1부터 100까지의 합(4의 배수 제외), 1000 넘으면 종료 ==>', hap;
END $$
DELIMITER ;
CALL whileProc2();

4. 동적 SQL

: SQL문은 내용이 고정되어 있는 경우가 대부분이다. 하지만 상황에 따라 내용 변경이 필요할 때, 동적 SQL을 사용하면 변경되는 내용을 실시간으로 적용시켜 사용할 수 있다.

1) PREPARE와 EXECUTE

(1) 의미

  • PREPRAE : SQL 문을 실행하지는 않고, 미리 준비만 해놓는다.

    • ex) PREPARE myQuery FROM 'INSERT INTO gate_table VALUES (NULL, ?)';

  • ESECUTE : 준비한 SQL문을 실행한다.

    • EXECUTE myQuery USING @curDate;

  • DEALLOCATE PREPARE : 실행한 후에는 문장을 해제해주는 것이 바람직하다.

2) 동적 SQL의 활용

(1) 물음표(?)의 사용

: PREPARE 문에서는 ?로 향후에 입력될 값을 비워놓고, EXECUTE에서 USING으로 ?에 값을 전달할 수 있다.

: 이를 통해 실시간으로 필요한 값을 전달해서 동적으로 SQL이 실행된다.


12강

0. 개요

  • 테이블은 표로 구성된 2차원 구조로, 행과 열로 구성되어 있다.

  • 행은 로우나 레코드라 부르며, 열은 컬럼 또는 필드라고 부른다.

1. 데이터베이스와 테이블 설계하기

1) 테이블의 구조 정의

: 테이블에 데이터 형식을 지정하는 데 정답은 없다.

2) 데이터베이스 만들기

SQL
DROP DATABASE IF EXISTS naver_db;
CREATE DATABASE naver_db;

3) 테이블 만들기

SQL
USE naver_db;
DROP TABLE IF EXISTS member;
CREATE TABLE member(
        mem_id CHAR(8) NOT NULL PRIMARY KEY,
    mem_name VARCHAR(10) NOT NULL,
    mem_number TINYINT NOT NULL,
    addr CHAR(2) NOT NULL,
    phone1 CHAR(3) NULL,
    phone2 CHAR(8) NOT NULL,
    height TINYINT UNSIGNED NOT NULL,
    debut_date DATE NOT NULL
);
  • PRIMARY KEY

  • NOT NULL

  • UNSIGNED

SQL
DROP TABLE IF EXISTS buy;
CREATE TABLE buy(
    num INT AUTO_INCREMENT NOT NULL PRIMARY KEY,
    mem_id CHAR(8) NULL,
    prod_name CHAR(6) NOT NULL,
    group_name CHAR(4) NULL,
    price INT UNSIGNED NOT NULL,
    amount SMALLINT UNSIGNED NOT NULL,
    FOREIGN KEY(mem_id) REFERENCES member(mem_id)
);

4) 데이터 입력하기

SQL
INSERT INTO member VALUES ('TWC', '트와이스', 9, '서울', '02', '11111111', 167, '2015-10-10');
INSERT INTO member VALUES ('BLK', '블랙핑크', 4, '경남', '055', '22222222', 163, '2016-08-08');
INSERT INTO member VALUES ('WMN', '여자친구', 6, '경기', '031', '33333333', 166, '2015-01-15');
SQL
INSERT INTO buy VALUES (NULL, 'BLK', '지갑', NULL, 30, 2);
INSERT INTO buy VALUES (NULL, 'BLK', '맥북프로', '디지털', 1000, 1);

13강

1. 제약조건의 기본 개념과 종류

  • 제약 조건은 데이터의 무결성을 지키기 위한 조건이다.

    • 데이터의 무결성 : 데이터에 결함이 없음

  • 이러한 결함을 방지하기 위해서 기본키를 지정할 수 있다.

  • 기본키의 조건 : 중복되지 않고, 비어 있지도 않음

  • 대표적인 제약 조건

    • 기본 키(Primary Key)

    • 외래 키(Foreign Key)

    • 고유 키 (Unique)

    • 체크(Check)

    • 기본값(Default) 정의

    • NOT NULL

2. 기본 키 제약조건

  • 기본 키 : 데이터를 구분할 수 있는 식별자

  • 예 : 회원 테이블의 아이디, 학생 테이블의 학번, 직원 테이블의 사번

  • 특징

    • 기본 키에 입력도니 값은 중복될 수 없으며, NULL 값이 입력될 수 없다.

    • 기본 키로 생성한 것은 자동으로 클러스터형 인덱스가 생성된다.

    • 테이블은 기본 키를 1개만 가질 수 있다.

  • 기본 키가 없어도 테이블 구성이 가능하지만, 실무에 사용하는 테이블에는 기본 키를 설정해야, 중복된 데이터가 입력되지 않는다.

1) CREATE TBALE에서 설정하는 기본 키 제약조건

(1) 열 자체에 지정

SQL
DROP TABLE IF EXISTS buy, member;
CREATE TABLE member
(
    mem_id   CHAR(8)          NOT NULL PRIMARY KEY,
    mem_name VARCHAR(10)      NOT NULL,
    height   TINYINT UNSIGNED NULL
);

(2) 열 밖에서 지정

SQL
DROP TABLE IF EXISTS member;
CREATE TABLE member
(
    mem_id   CHAR(8)          NOT NULL,
    mem_name VARCHAR(10)      NOT NULL,
    height   TINYINT UNSIGNED NULL,
    PRIMARY KEY (mem_id)
);

(3) 테이블 정보를 수정하여 지정

SQL
DROP TABLE IF EXISTS member;
CREATE TABLE member
(
    mem_id   CHAR(8)          NOT NULL,
    mem_name VARCHAR(10)      NOT NULL,
    height   TINYINT UNSIGNED NULL
);
ALTER TABLE member -- 테이블 정보를 수정하겠다
    ADD CONSTRAINT -- 제약 조건을 추가하겠다
        PRIMARY KEY (mem_id); -- 이 조건을

2) CONSTRAINT

  • 내용단순히 PK의 이름을 지정하는 것뿐만 아니라, 나중에 해당 제약 조건을 쉽게 참조하거나 변경할 수 있도록 하기 위해서도 사용된다.

    1. 명확한 제약 조건 관리: 기본 키뿐만 아니라 UNIQUE, CHECK, FOREIGN KEY 등 여러 제약 조건을 정의할 때 이름을 부여하면 쉽게 관리할 수 있다.

    2. 제약 조건 삭제 및 수정 용이: 특정 제약 조건을 삭제하거나 변경할 때 이름이 있으면 더 편리하다.

    3. ALTER TABLE member DROP CONSTRAINT PK_member_mem_id;

    4. 가독성 향상: 여러 개의 제약 조건이 존재하는 경우, 명확한 이름을 부여하면 코드의 가독성이 좋아진다.```sql

    5. 예제 (CONSTRAINT 사용 vs 미사용)

    -- CONSTRAINT 없이 기본 키 지정CREATE TABLE member ();이처럼 CONSTRAINT를 사용하면 PK의 이름을 직접 지정할 수 있고, 나중에 관리하기도 편하다.

  • ```sql -- CONSTRAINT로 기본 키에 이름 지정 CREATE TABLE member ( mem_id CHAR(8) NOT NULL, mem_name VARCHAR(10) NOT NULL, CONSTRAINT PK_member_mem_id PRIMARY KEY (mem_id) );

  • mem_id CHAR(8) NOT NULL PRIMARY KEY, mem_name VARCHAR(10) NOT NULL

  • CONSTRAINT를 사용하는 이유

  • CONSTRAINT제약 조건(Constraint)에 이름을 부여하고 관리하기 위해 사용된다.

3. 외래 키 제약조건

  • 외래 키 제약 조건은 두 테이블 사이의 관계를 연결해주고, 그 결과 데이터의 무결성을 보장해주는 역할을 한다.

  • 외래 키가 설정된 열은 꼭 다른 테이블의 기본 키와 연결된다.

  • 기본 키가 있는 테이블을 ‘기준 테이블’이라 부르고, 외래 키가 있는 테이블을 ‘참조 테이블’이라고 부른다.

  • 참조 테이블이 참조하는 기준 테이블은 반드시 기본 키(Primary Key)나 고유키(Unique)로 걸정되어 있어야 한다.

1) CREAT TABLE에서 설정하는 외래 키 제약 조건

  • CREATE TABLE 끝에 FOREGIEN KEY를 설정

(1) 열 자체에 지정

SQL
USE naver_db;

DROP TABLE IF EXISTS buy, member;
CREATE TABLE member
(
    mem_id   CHAR(8)          NOT NULL PRIMARY KEY,
    mem_name VARCHAR(10)      NOT NULL,
    height   TINYINT UNSIGNED NULL
);

CREATE TABLE buy
(
    num       INT AUTO_INCREMENT NOT NULL PRIMARY KEY,
    mem_id    CHAR(8)            NOT NULL,
    prod_name CHAR(6)            NOT NULL,
    FOREIGN KEY (mem_id) REFERENCES member (mem_id)
);

-- 외래 키의 이름도 바꿀 수 있다. (히지만 혼란을 위해 동일한 이름을 권장한다.)
DROP TABLE IF EXISTS buy, member;
CREATE TABLE member
(
    mem_id   CHAR(8)          NOT NULL PRIMARY KEY,
    mem_name VARCHAR(10)      NOT NULL,
    height   TINYINT UNSIGNED NULL
);

CREATE TABLE buy
(
    num       INT AUTO_INCREMENT NOT NULL PRIMARY KEY,
    user_id   CHAR(8)            NOT NULL,
    prod_name CHAR(6)            NOT NULL,
    FOREIGN KEY (user_id) REFERENCES member (mem_id)
);

(2) 테이블 정보를 수정하여 지정

SQL
DROP TABLE IF EXISTS buy;
CREATE TABLE buy
(
    num       INT AUTO_INCREMENT NOT NULL PRIMARY KEY,
    mem_id   CHAR(8)            NOT NULL,
    prod_name CHAR(6)            NOT NULL
);
ALTER TABLE buy
    ADD CONSTRAINT
        FOREIGN KEY (mem_id) REFERENCES member (mem_id);

2) 기준 테이블의 열이 변경될 경우

(1) 문제가 되는 상황

SQL
INSERT INTO member VALUES ('BLK', '블랙핑크', 163);
INSERT INTO buy VALUES (NULL, 'BLK', '지갑');
INSERT INTO buy VALUES (NULL, 'BLK', '맥북');

-- 검색
SELECT M.mem_id, M.mem_name, B.prod_name
    FROM buy B
        INNER JOIN member M
        ON B.mem_id = M.mem_id;

-- PK와 FK로 연결되어 있기에, 변경/삭제가 불가능하다. (데이터 무결성을 보장하기 위해서)
UPDATE member SET mem_id = 'PINK' WHERE mem_id = 'BLK';
DELETE FROM member WHERE mem_id = 'BLK';

(2) 해결 방법

  • 기준 테이블의 PK의 내용이 바뀌게 되면, 참조 테이블의 FK도 다 변경되게끔 한다.

  • ON UPDATE CASCADE

  • ON DELETE CASCADE

SQL
DROP TABLE IF EXISTS buy;
CREATE TABLE buy
(
    num       INT AUTO_INCREMENT NOT NULL PRIMARY KEY,
    mem_id    CHAR(8)            NOT NULL,
    prod_name CHAR(6)            NOT NULL
);

-- 테이블 정보 수정
ALTER TABLE buy
    ADD CONSTRAINT
        FOREIGN KEY (mem_id) REFERENCES member (mem_id)
            ON UPDATE CASCADE
            ON DELETE CASCADE;

INSERT INTO buy VALUES (NULL, 'BLK', '지갑');
INSERT INTO buy VALUES (NULL, 'BLK', '맥북');

-- 검색 (BLK인 상태)
SELECT M.mem_id, M.mem_name, B.prod_name
    FROM buy B
        INNER JOIN member M
        ON B.mem_id = M.mem_id;

-- PK 수정
UPDATE member SET mem_id = 'PINK' WHERE mem_id = 'BLK';
-- 검색 (PINK로 바뀐 상태)
SELECT M.mem_id, M.mem_name, B.prod_name
    FROM buy B
        INNER JOIN member M
        ON B.mem_id = M.mem_id;

-- PK 삭제
DELETE FROM member WHERE mem_id = 'PINK';
-- 검색
SELECT * FROm buy;

4. 기타 제약조건

1) 고유 키 제약 조건

  • 고유 키(Unique) 제약 조건은 ‘중복되지 않는 유일한 값’을 입력해야 하는 조건이다.

  • 기본 키 제약조건과 거의 비슷하지만, 차이점은 고유 키 제약조건은 NULL 값을 허용한다.

  • 예 : 아이디는 있는 상태에서 이메일에 대해 중복을 주고 싶지 않을 때.

SQL
DROP TABLE IF EXISTS buy, member;
CREATE TABLE member
(
    mem_id   CHAR(8)          NOT NULL PRIMARY KEY,
    mem_name VARCHAR(10)      NOT NULL,
    height   TINYINT UNSIGNED NULL,
    email    CHAR(30)         NULL UNIQUE
);

-- 정상
INSERT INTO member VALUES ('BLK', '블랙핑크', 163, 'pink@gmail.com');
INSERT INTO member VALUES ('TWC', '트와이스', 167, NULL);
-- 오류 : 이메일 중복
INSERT INTO member VALUES ('APN', '에이핑크', 164, 'pink@gmail.com');

2) 체크 제약조건

  • 체크 제약조건은 입력되는 데이터를 점검하는 기능을 한다.

  • 예 : 평균 키(height)에 마이너스 값이 입력되지 않도록 하거나, 연락처 국번에 03, 031, 041, 055 중 하나만 입력되도록 할 수 있다.

(1) 값의 범위

SQL
DROP TABLE IF EXISTS buy, member;
CREATE TABLE member
(
    mem_id   CHAR(8)          NOT NULL PRIMARY KEY,
    mem_name VARCHAR(10)      NOT NULL,
    height   TINYINT UNSIGNED NULL CHECK ( height >= 100 ),
    phone1   CHAR(3)          NULl
);

-- 정상
INSERT INTO member VALUES ('BLK', '블랙핑크', 163, NULL);
-- 오류
INSERT INTO member VALUES ('TWC', '트와이스', 99, NULL);

(2) 일정 범위 중 일부만 입력

SQL
-- 연락처(phone1의 범위 지정)
ALTER TABLE member
    ADD CONSTRAINT
    CHECK (phone1 IN ('02', '031', '032', '054', '055', '061'));

-- 정상
INSERT INTO member VALUES ('TWC', '트와이스', 163, '02');
-- 오류
INSERT INTO member VALUES ('OMY', '오마이걸', 99, '010');

3) 기본값 정의

  • 기본값(Default) 정의는 입력하지 않았을 때 자동으로 입력될 값을 미리 지정해 놓는 방법이다.

  • 예 : 키를 입력하지 않고 기본적으로 160이라고 입력되도록 하고 싶은 경우

SQL
DROP TABLE IF EXISTS member;
CREATE TABLE member
(
    mem_id   CHAR(8)          NOT NULL PRIMARY KEY,
    mem_name VARCHAR(10)      NOT NULL,
    height   TINYINT UNSIGNED NULL DEFAULT 160,
    phone1   CHAR(3)          NULl
);

-- CONSTAINT와 문법이 조금 다르다.
ALTER TABLE member
    ALTER COLUMN phone1 SET DEFAULT '02';

-- 정상
INSERT INTO member VALUES ('RED', '레드벨벳', 163, '054');
-- 기본값을 사용
INSERT INTO member VALUES ('SPC', '우주소녀', default, default);

SELECT * FROM member;
  • INSERT 입력 시, VALUES에서 default 키워드를 사용하여 기본값을 사용한다.

4) 널 값 허용

  • 널(NULl) 값을 허용하려면 생략하거나 NULL을 사용하고, 허용하지 않으려면 NOT NULL을 사용한다.

  • 다만 PRIMARY KEY가 설정된 열에 NULl 값이 잇을 수 없으므로, 생략하면 자동으로 NOT NULL로 인식된다.

  • NULl 값은 ‘아무 것도 없다’라는 의미이며, 공백(’’)이나 0과는 다르다.


14강

0. 개요

  • 뷰는 데이터베이스 개체 중 하나이다.

  • 뷰는 한 번 생성해 놓으면, 테이블이라고 생각하고 사용해도 될 정도로, 사용자들의 입장에서는 테이블과 거의 동일한 개체로 취급된다.

  • 뷰의 종류 : 단순 뷰(하나 테이블과 연관된 뷰), 복합 뷰(2개 이상의 테이블과 연관된 뷰)

1) 뷰의 기본 생성

(1) 형태

SQL
CREATE VIEW 뷰_이름
AS
    SELECT 문;

(2) 뷰를 만든 후 접근 방법

SQL
SELECT 열_이름 FROM 뷰_이름
    [WHERE 조건];

(3) 예시

SQL
-- 뷰 생성
CREATE VIEW v_member
AS
SELECT mem_id, mem_name, addr
FROM member;

-- 뷰로부터 검색
SELECT *
FROM v_member;

SELECT mem_name, addr
FROM v_member
WHERE addr In ('서울', '경기');

2) 뷰의 작동 방식

  • 뷰는 기본적으로 ‘읽기 전용’으로 사용되지만, 뷰를 통해서 원본 테이블의 데이터를 수정할 수도 있다.

  • 하지만 무조건 가능한 것은 아니고, 몇 가지 조건을 만족해야 한다.

3) 뷰를 사용하는 이유

(1) 보안(security)에 도움이 된다.

  • 앞의 예에서 만든 v_member 뷰에는 사용자의 아이디, 이름, 주소만 있을 분 사용자의 중요한 개인 정보인 연락처, 평균 키, 데뷔 일자 등의 정보는 들어 있지 않다.

(2) 복잡한 SQL을 단순하게 만들 수 있다.

code
-- 복잡한 쿼리문
SELECT B.mem_id, M.mem_name, B.prod_name, M.addr, CONCAT(M.phone1, M.phone2) '연락처'
FROM buy B
         INNER JOIN member M
                    ON B.mem_id = M.mem_id;

-- 뷰를 생성
CREATE VIEW v_memberbuy
AS
SELECT B.mem_id, M.mem_name, B.prod_name, M.addr, CONCAT(M.phone1, M.phone2) '연락처'
FROM buy B
         INNER JOIN member M
                    ON B.mem_id = M.mem_id;

-- 뷰를 사용하여 검색하면 복잡한 SQL문을 단순하게 할 수 있다.
SELECT * FROM v_memberbuy WHERE mem_name = '블랙핑크';

1. 뷰의 실제 작동

1) 뷰의 실제 생성, 수정, 삭제

  • 기본적인 뷰를 생성하면서 뷰에서 사용될 열 이름을 테이블과 다르게 지정할 수도 있다.

  • 별칭을 사용하면 되는데, 중간에 띄어쓰기 사용이 가능하다.

  • 별칭은 이름 뒤에 작은따옴표 또는 큰따옴표로 묶어주고, 형식상 AS를 붙여준다.

  • 단 뷰를 조회할 때 열 이름에 공백이 있으면 백틱(`)으로 묶어줘야 한다.

(1) 뷰의 생성, 뷰 컬럼의 수정

SQL
-- 뷰의 생성
CREATE VIEW v_viewtest1
AS
SELECT B.mem_id                      'Member ID',
       M.mem_name                 AS 'Member Name',
       B.prod_name                   "Product Name",
       CONCAT(M.phone1, M.phone2) AS "Office Phone"
FROM buy B
         INNER JOIN member M
                    ON B.mem_id = M.mem_id;

SELECT DISTINCT `Member ID`, `Member Name`
FROM v_viewtest1;

-- 뷰의 수정
ALTER VIEW v_viewtest1
AS
    SELECT B.mem_id                   '회원 아이디',
        M.mem_name                 AS '회원 이름',
        B.prod_name                   "제품 이름",
        CONCAT(M.phone1, M.phone2) AS "연락처"
    FROM buy B
        INNER JOIN member M
            ON B.mem_id = M.mem_id;

SELECT DISTINCT `회원 아이디`, `회원 이름`
FROm v_viewtest1;

-- 뷰의 삭제
DROP VIEW v_viewtest1;

(2) 뷰 생성 시, 이미 존재하는 뷰일 경우 덮어 쓰는 방법

SQL
-- 뷰가 있으면 덮어 써서 생성한다.
CREATE OR REPLACE VIEW v_viewtest2
AS
SELECT mem_id, mem_name, addr
FROM member;

2) 뷰의 정보 확인

  • 기존에 생성된 뷰에 대한 정보를 확인할 수 있다.

(1) 형식

SQL
DESCRIBE 뷰_이름;

(2) 예시

SQL

DESCRIBE v_viewtest2;

-- 뷰를 생성하던 쿼리문 보기
SHOW CREATE VIEW v_viewtest2;

3) 뷰의 컬럼의 내용 수정

SQL
-- 뷰의 내용 수정
UPDATE v_member
SET addr = '부산'
WHERE mem_id = 'BLK';

SELECT * FROM v_member;
  • v_member, member 테이블에서 모두 값이 수정된다. (사실상, 실제 값이 수정되는 것이다.)

4) 뷰에 입력 [case : 오류 발생]

SQL
-- 뷰에 입력하려고 하는 경우 : 오류 발생 (NOT NULl이 존재해서)
-- 따라서 뷰를 통해서 입력이 될 수도 있지만, 안 될 수도 있다.
-- Default를 사용하게 되면, NOT NULL의 제약 조건을 만족시킬 수 있게 된다.
INSERT INTO v_member(mem_id, mem_name, addr) VALUES ('BTS', '방탄소년단', '경기');

5) 다양한 상황

(1) 문제점 : 잘못된 입력 및 삭제인 상황

SQL
CREATE VIEW v_height167
AS
SELECT *
FROM member
WHERE height >= 167;

-- 뷰 조회 : height가 167 이상인 레코드만 보여준다. 
SELECT *
FROM v_height167;

-- 상황1 : 뷰에서 행을 삭제하지만, 0개가 삭제된다.
DELETE
FROM v_height167
WHERE height < 167;

-- 상황2 : 입력은 성공해서 테이블에 들어가긴 한다.
INSERT INTO v_height167
VALUES ('TRA', '티아라', 6, '서울', NULL, NULL, 159, '2005-01-01');
-- 하지만 조회가 안 된다.
SELECT *
FROM v_height167; -- 존재하지 않는다.
SELECT *
FROM member; -- 존재한다.

(2) 솔루션 : 입력이 삭제된다.

SQL
-- 뷰의 조건 수정
ALTER VIEW v_height167
AS
    SELECT * FROM member WHERE height >= 167
        WITH CHECK OPTION;
-- 입력이 실패한다.
INSERT INTO v_height167
VALUES ('TOB', '텔레토비', 4, '영국', NULL, NULL, 140, '1995-01-01');

6) 뷰의 부모인 원본 테이블이 삭제된 경우

SQL
-- 테이블 삭제
DROP TABLE IF EXISTS buy, member;

-- 오류 발생
SELECT * FROM v_height167;

-- 왜 조회가 안 되는지 탐색 : MySQL에서 특정 테이블 또는 뷰의 무결성을 검사하는 명령어
CHECK TABLE v_height167;
목차
  1. 9강
  2. 1. 데이터 형식
  3. 1) 정수형
  4. 2) 문자형
  5. 3) 대량의 데이터 형식
  6. 4) 실수형
  7. 5) 날짜형
  8. 2. 변수의 사용
  9. 1) 선언 및 대입
  10. 2) 출력
  11. 3) PREPARE / EXECUTE
  12. 3. 데이터 형 변환
  13. 1) 의미
  14. 2) 종류
  15. 3) 명시적인 변환
  16. 4) 암시적인 형 변환
  17. 10강
  18. 0. 개요
  19. 1) 조인 (join)
  20. 1. 내부 조인
  21. 1) 형식
  22. 2) 특정 열에 대한 지정
  23. 3) 테이블의 별칭
  24. 4) 내부 조인의 한계
  25. 5) 기본키 / 외래키
  26. 2. 외부 조인 (Outer JOIN)
  27. 1) 형식
  28. 3. 기타 조인
  29. 1) 상호 조인 (CROSS JOIN)
  30. 2) 자체 조인 (Self JOIN)
  31. 11강
  32. 0. 개요
  33. 1) 스토어드 프로시저
  34. 1. IF문
  35. 1) IF 문의 기본 형식
  36. 2) IF ~ ELSE문
  37. 3) 응용
  38. 2. CASE문
  39. 1) CASE문의 기본 형식
  40. 2) CASE 문의 활용
  41. 3. WHILE문
  42. 1) WHILE문의 기본 형식
  43. 2) WHILE문의 응용
  44. 4. 동적 SQL
  45. 1) PREPARE와 EXECUTE
  46. 2) 동적 SQL의 활용
  47. 12강
  48. 0. 개요
  49. 1. 데이터베이스와 테이블 설계하기
  50. 1) 테이블의 구조 정의
  51. 2) 데이터베이스 만들기
  52. 3) 테이블 만들기
  53. 4) 데이터 입력하기
  54. 13강
  55. 1. 제약조건의 기본 개념과 종류
  56. 2. 기본 키 제약조건
  57. 1) CREATE TBALE에서 설정하는 기본 키 제약조건
  58. 2) CONSTRAINT
  59. 3. 외래 키 제약조건
  60. 1) CREAT TABLE에서 설정하는 외래 키 제약 조건
  61. 2) 기준 테이블의 열이 변경될 경우
  62. 4. 기타 제약조건
  63. 1) 고유 키 제약 조건
  64. 2) 체크 제약조건
  65. 3) 기본값 정의
  66. 4) 널 값 허용
  67. 14강
  68. 0. 개요
  69. 1) 뷰의 기본 생성
  70. 2) 뷰의 작동 방식
  71. 3) 뷰를 사용하는 이유
  72. 1. 뷰의 실제 작동
  73. 1) 뷰의 실제 생성, 수정, 삭제
  74. 2) 뷰의 정보 확인
  75. 3) 뷰의 컬럼의 내용 수정
  76. 4) 뷰에 입력 [case : 오류 발생]
  77. 5) 다양한 상황
  78. 6) 뷰의 부모인 원본 테이블이 삭제된 경우