티스토리 뷰
목차
📍 데이터 정의어 (DDL)
2-1. 제약조건 생성
3. 테이블 수정 (ALTER TABLE)
3-1. 컬럼 추가
3-3. 컬럼 삭제
3-5. 제약조건 확인
3-6. 제약조건 삭제
📍 데이터 정의어 (DDL)
– Data Definition Language
– 오브젝트의 구조를 정의하는 명령어.
– DDL 구문은 하나의 구문이 하나의 트랜잭션으로 동작함.
→ 주의! 구문 실행 시 자동으로 commit이 실행됨.
– UPDATE & DELETE는 '데이터'의 값을 변경하고 삭제하는 것, ALTER & DROP은 '구조'를 변형하고 삭제하는 것.
ex ) 테이블 구조를 통으로 날릴 때, 즉 테이블 삭제할 때는 DROP 키워드를 사용함.
▸ 오브젝트의 구조를 정의하는 명령어
1. CREATE
– 오브젝트 구조를 생성하는 명령어.
2. ALTER
– 기존 오브젝트의 구조를 변형하는 명령어.
3. DROP
– 기존 오브젝트의 구조를 삭제하는 명령어.
▸ 데이터베이스 생성 (CREATE DATABASE)
CREATE DATABASE shopdb;
SHOW DATABASES;
USE shopdb;
– 연습용 DB, 'shopdb' 생성함.
📍 테이블 생성 (CREATE TABLE)
CREATE TABLE 테이블명
컬럼명 데이터타입 [제약조건] [옵션],
컬럼명 데이터타입 [DEFAULT default값],...컬럼명 데이터타입;
– 테이블 생성 시 테이블명, 컬럼명, 데이터타입 지정해야 함.
• 옵션
1 ) 제약조건
2 ) DEFAULT 값
– NULL 값 방지 & 내가 직접 입력하기 애매한 것 ( = NOW() )
3 ) AUTO_INCREMENT 옵션
– 자동으로 증가하는 숫자를 할당하는 기능.
– 주로 PK 제약조건 컬럼에 적용하며 테이블 당 하나만 사용 가능.
– 정수 데이터만 가능하며 1부터 시작해서 1씩 증가한 값을 자동으로 작성해줌.
– 데이터 추가시 AUTO_INCREMENT가 적용된 컬럼에는 값을 입력하지 않음.
EX ) |
• DEFAULT 값이 포함된 테이블 생성
CREATE TABLE dept
(deptno int,
dname varchar(14),
loc varchar(13),
create_date datetime DEFAULT now());
DESC dept;
– DEFAULT 값으로 now라고 입력했지만 current_timestamp로 입력됨. NOW는 도태될 문법이라 자동으로 바뀜.
✓ 실행 결과
• 데이터 입력하기
INSERT INTO dept (deptno, dname)
VALUES (10, '재택');
SELECT * FROM dept;
– create_date 컬럼에는 DEFAULT 값으로 NOW 함수를 입력해놨으므로,
내가 실제로 데이터를 입력한 날짜 및 시간이 입력됨.
✓ 실행 결과
💡 ENUM 데이터타입
※ 개요
– MySQL에서 ENUM 데이터 타입은 열(column)에 저장할 수 있는 값들의 목록을 미리 정의하고,
해당 열에서 사용할 수 있는 값으로 제한하는 데이터 타입.
– 목록에 없는 값을 입력하면 에러 발생함.
– 목록 값은 문자열 데이터로 작성되어야 함.
– 입력을 허용할 값을 테이블의 설정에 기록하는 형태이기 때문에
입력값의 목록을 수정하려면 ALTER TABLE의 문법을 사용해야 하는데,
유연하게 목록의 값을 조정하는 것이 어려움.
– 입력 값에 대해서 참조 할 수 있는 값이 테이블에 있다면
외래키 제약조건을 적용해주는 것이 좀 더 나은 방법일 수 있음.
– ENUM 데이터타입은 단순하고 빠르지만, 수정이 어렵기 때문에 주의해서 사용해야 함.
※ 문법
CREATE TABLE table_name (
column_name ENUM('value1', 'value2', 'value3', ...)
);
※ 예제
CREATE TABLE fruits (
id INT AUTO_INCREMENT PRIMARY KEY,
fruit ENUM('apple', 'banana', 'orange', 'grape')
);
▸ 제약조건 생성 (Constraint)
1. NOT NULL
– 컬럼에 null값을 허용하지 않는 제약조건.
– 값이 반드시 있어야하는 필수 컬럼에 not null 제약조건을 지정함.
– null값이 입력되는 경우 에러가 발생하며, 행의 값이 입력되지 않음.
– null값 저장 시, 고정 길이 문자형(char)은 공간 모두 차지, 가변 길이 문자형(varchar)은 공간 차지 X
null값이 많이 입력되는 컬럼은 varchar를 사용하는 것을 권장함.
EX ) |
• not null 제약조건이 포함된 테이블 생성
CREATE TABLE test1
( id int NOT NULL,
name varchar(30) NOT NULL,
jumin varchar(13) NOT NULL,
job varchar(20),
email varchar(20),
phone varchar(20) NOT NULL,
start_date date );
DESC test1;
✓ 실행 결과
• 데이터 입력
INSERT INTO test1 (id, name, jumin, phone, start_date)
VALUES (1, 'Kim', 'abcd', '123', '2023-03-24');
SELECT * FROM test1;
✓ 실행 결과
🚨주의🚨
INSERT INTO test1 (id, name)
VALUES (2, 'Lee');
– SQL Error [1364] [HY000]: Field 'jumin' doesn't have a default value.
→ jumin, phone 컬럼은 not null 제약조건으로 null값을 입력할 수 없으므로,
컬럼에 입력값을 주지 않을 때 default 설정도 없다면 에러 발생함.
2. unique
– 중복되지 않는 유일한(고유한) 값을 입력해야 하는 제약조건.
– 중복된 값은 허용하지 않으나 null값은 허용함.
또한, null값은 모르는 값(값을 비교할 수 없는 데이터)으로 null값끼리는 동일한 값이 아니라 여러 개 입력될 수 있음.
– 중복된 값이 들어와서는 안되는 주민번호, 전화번호, 메일 등의 컬럼에 활용됨.
EX ) |
• not null 제약조건이 포함된 테이블 생성
CREATE TABLE test2
( id int NOT NULL UNIQUE,
name varchar(30) NOT NULL,
jumin varchar(13) NOT NULL UNIQUE,
job varchar(20),
email varchar(20) NOT NULL UNIQUE,
start_date date );
DESC test2;
– Key의 항목에서 unique 제약조건이 적용된 컬럼은 값이 UNI로 표기됨.
– 테이블에 primary key 제약조건이 없는 경우, not null + unique 조합의 첫 컬럼이 primary key 인식.
✓ 실행 결과
• 데이터 입력
INSERT INTO test2 (id, name, jumin, phone)
VALUES (1, 'Hi', '123', '051');
SELECT * FROM test2;
✓ 실행 결과
🚨주의🚨
INSERT INTO test2 (id, name, jumin, phone)
VALUES (2, 'Hi', '123', '053');
– SQL Error [1062] [23000]: Duplicate entry '123' for key 'test2.jumin'
→ jumin 컬럼에 중복값을 입력하는 경우 에러 발생.
INSERT INTO test2 (id, name, jumin, phone)
VALUES (2, 'Hi', '456', '053');
– email 컬럼은 unique 제약조건이 적용되어 있으나,
null값은 중복값 비교 자체가 불가능하기 때문에 null 값은 여러 값을 입력할 수 있음.
SELECT * FROM test2;
✓ 실행 결과
3. primary key
– 테이블의 행을 고유하게 식별해 줄 수 있는 컬럼(대표컬럼)에 선언하는 기본키 제약조건.
– not null + unique의 성격을 모두 가지는 제약조건.
– not null과 unique의 제약을 적용받는 후보 컬럼들 중,
외부에 공개되어도 되는 정보와 검색하기 좋은 조건을 가지는 테이블을 대표하는 컬럼에 적용함.
– 주로 사번, 학번, 회원번호, 제품번호, 주분번호 등의 컬럼에 선언함.
– 테이블당 한 번만 사용 가능.
EX ) |
• primary key 제약조건이 포함된 테이블 생성
CREATE TABLE test3
( id int PRIMARY KEY,
name varchar(30) NOT NULL,
jumin varchar(13) NOT NULL UNIQUE,
job varchar(20),
email varchar(20) UNIQUE,
phone varchar(20) NOT NULL UNIQUE,
start_date date );
DESC test3;
✓ 실행 결과
• 데이터 입력
INSERT INTO test3 (id, name, jumin, phone)
VALUES (1, 'Hi', '123', '051');
– 똑같은 쿼리로 데이터 한번 더 입력해봄.
INSERT INTO test3 (id, name, jumin, phone)
VALUES (1, 'Hi', '123', '051');
– SQL Error [1062] [23000]: Duplicate entry '1' for key 'test3.PRIMARY'
→ 같은 값을 두번 입력하는 경우, PRI제약이 걸려 있는 id컬럼에서 중복 데이터라 에러 발생함.
• 제약조건 조회하기
SHOW DATABASES;
✓ 실행 결과
SELECT * FROM information_schema.table_constraints
WHERE constraint_schema = 'shopdb'
AND table_name = 'test3';
– test3 테이블에 적용된 제약조건 정보를 알 수 있음.– constraint_name은 자동 생성된 제약조건의 이름. 컬럼명 아님!
✓ 실행 결과
※ 보통 GUI 개발 도구 (DBeaver 등)들은 테이블 설정 정보를 조회할 수 있는 메뉴를 제공함.
4. foreign key
– 두 테이블 사이의 관계를 선언함으로써, 데이터의 무결성을 보장해 주는 외래키 제약조건.
– 자기 자신 테이블이나 다른 테이블의 특정 컬럼을 참조하는 제약조건.
→ 단, primary key 또는 unique 제약조건이 선언된 컬럼만 참조할 수 있음.
– foriegn key 제약조건이 선언된 컬럼 = 자식 컬럼
– foriegn key 제약조건이 참조하는 컬럼 = 부모 컬럼
– 자식 컬럼에는 부모 컬럼에 있는 데이터 중 하나만 삽입, 수정될 수 있음.
• 문법 (테이블레벨)
– 테이블 레벨의 제약조건 선언은 컬럼의 정의와 제약조건의 정의를 별도로 작성하는 방법.
→ 따라서 제약조건이 적용될 컬럼을 설정해줘야 함.
– 외래키 제약조건의 경우 references절을 통해서 참조할 테이블 컬럼을 지정할 수 있음.
foreign key (컬럼명) references 테이블명 (컬럼명)
자식컬럼 절 부모 테이블 & 컬럼명
EX ) |
• foreign key 제약조건이 포함된 테이블 생성
CREATE TABLE test4
( t_num int PRIMARY KEY, -- 컬럼 레벨
t_id int,
title varchar(20) NOT NULL,
story varchar(100) NOT NULL,
FOREIGN key(t_id) REFERENCES test3(id) ); -- 테이블 레벨
DESC test4;
– t_id컬럼의 Key항목이 Multi Key의 줄임말인 'MUL'로 나옴.
– MUL = Multi key (FK + index ) 뒤에가서 자세히 배움.
✓ 실행 결과
• test3 테이블에 데이터 추가 입력
INSERT INTO test3 (id, name, jumin, phone)
VALUES (2, 'Hi2', '444', '02');
INSERT INTO test3 (id, name, jumin, phone)
VALUES (3, 'Hi3', '112123', '02351');
– test4 테이블에 데이터를 물려주기 위해 데이터를 여러개 추가함.
• test4 테이블에 데이터 입력 1
INSERT INTO test4
VALUES (10, 1, 'ti', 'sto');
– 제약조건이 걸린 대로 알맞게 데이터를 입력함.
• test4 테이블에 데이터 입력 2
INSERT INTO test4
VALUES (20, 5, 'ti', 'sto');
– SQL Error [1452] [23000]: Cannot add or update a child row: a foreign key constraint fails (`shopdb`.`test4`,
CONSTRAINT `test4_ibfk_1` FOREIGN KEY (`t_id`) REFERENCES `test3` (`id`))
– 제약조건이 걸린 대로 알맞게 데이터를 입력했으나 에러 발생.
– test4의 두번째 컬럼인 t_id는 test3의 id 컬럼을 참조하는 외래키로 id컬럼에 없는 값을 입력할 수 없음.
→ 현재 test3.id 컬럼에는 1, 2, 3의 값들만 있음.
→ 외래키 제약이 걸려있는 t_id컬럼이 참조하는 부모 컬럼에 '5'라는 데이터가 없으므로 에러 발생함.
INSERT INTO test4
VALUES (20, 3, 'ti', 'sto');
– 위의 코드에서 '5' 데이터를 '3'으로 수정하면 데이터 입력 가능.
→ 부모 컬럼에 '3' 데이터가 있음.
SELECT * FROM test4;
✓ 실행 결과
• 데이터 삭제
DELETE FROM test3
WHERE id = 1;
– SQL Error [1451] [23000]: Cannot delete or update a parent row: a foreign key constraint fails (`shopdb`.`test4`,
CONSTRAINT `test4_ibfk_1` FOREIGN KEY (`t_id`) REFERENCES `test3` (`id`))
– test3의 id가 1인 행을 삭제 시 외래키 제약조건에 의해서 실패
→ 현재 자식 테이블인 test4에서 t_id 컬럼의 값들 중 1의 값을 물려받아 사용 중이기 때문에
부모의 값을 마음대로 삭제하지 못하도록 제약조건에서 차단함.
→ 부모의 값을 삭제하려면 먼저 자식이 가지고 있는 값들을 다른 값으로 바꾸거나 삭제 후 진행 가능.
– 자식이 사용 중이지 않은 값에 대해서는 삭제나 갱신이 문제 없이 가능함.
• ON DELETE CASCADE 옵션
– test3(id) 컬럼은 부모 컬럼으로 t_id 컬럼이 값을 참조하고 있다면,
데이터를 마음대로 삭제할 수 없도록 제한이 되어 있음. (기본값인 NO ACTION 옵션)
– 다만 ON DELETE CASCADE 옵션을 외래키에 추가하는 경우,
부모의 값을 삭제 할 때 자식의 값도 종속적으로 삭제를 시켜 주는 형태로 동작을 하게 됨.
– 연결 된 자식 데이터가 파악되지 않은 상태에서 사용하면 의도치 않은 데이터가 삭제되는 위험한 문법일 수 있으나,
자식 데이터가 잘 파악이 된 상태에서 사용하는 것은 일관성을 유지하는데 도움이 됨.
CREATE TABLE heart
( num int,
rest_id varchar(45),
user_id varchar(45),
FOREIGN KEY (rest_id) REFERENCES restaurant(rest_id) ON DELETE CASCADE,
FOREIGN KEY (user_id) REFERENCES user(user_id) ON DELETE CASCADE
);
5. check
– 해당 컬럼이 만족해야하는 조건을 지정하는 제약조건.
– 조건식을 작성하여 조건을 만족하는 값만 입력과 갱신을 허용함.
EX ) |
• check 제약조건이 포함된 테이블 생성
CREATE TABLE test5
( id int(10) PRIMARY KEY,
name varchar(30) NOT NULL,
jumin varchar(13) NOT NULL UNIQUE CHECK (LENGTH(jumin)=13),
job varchar(20),
email varchar(20) UNIQUE,
phone varchar(20) NOT NULL UNIQUE,
start_date date CHECK (start_date >= '2005-01-01') );
DESC test5;
✓ 실행 결과
• 제약조건 조회하기
SELECT * FROM information_schema.table_constraints
WHERE table_name = 'test5';
✓ 실행 결과
• DBeaver로 조회하기
• 데이터 입력
INSERT INTO test5 (id, name, jumin, phone)
VALUES (1, 'hihi', '1234567890123', '2039');
SELECT * FROM test5;
– 설정한 제약조건이 모두 맞으므로 해당 데이터가 문제없이 입력됨.
✓ 실행 결과
• 데이터 입력 2
INSERT INTO test5 (id, name, jumin, phone)
VALUES (2, 'hihi', '12345678901', '2040');
– SQL Error [3819] [HY000]: Check constraint 'test5_chk_1' is violated.
→ test5 테이블의 check 제약조건 첫번째에서 조건을 만족하지 못해 에러 발생.
Q ) shopdb 데이터베이스 (스키마)에서 테이블을 아래 조건에 알맞게 생성하시오. (p.156)
A )
1. TITLE 테이블 생성하기
CREATE TABLE TITLE
( TITLE_ID int PRIMARY KEY,
TITLE varchar(60) NOT NULL,
DESCRIPTION varchar(400) NOT NULL,
RATING varchar(4) CHECK (RATING IN ('G', 'PG', 'R', 'NC17', 'NR')),
CATEGORY varchar(20) CHECK (CATEGORY IN ('DRAMA', 'COMEDY', 'ACTION', 'CHILD', 'SCIFI', 'DOCUMENTARY')),
RELEASE_DATE date);
DESC title;
✓ 실행 결과
2. TITLE_COPY 테이블 생성하기
CREATE TABLE TITLE_COPY
( COPY_ID int PRIMARY KEY,
TITLE_ID int PRIMARY KEY,
STATUS varchar(15) NOT NULL CHECK (STATUS IN ('AVAILABLE', 'DESTROYED', 'RENTED', 'RESERVED')),
FOREIGN KEY (TITLE_ID) REFERENCES TITLE(TITLE_ID));
– SQL Error [1068] [42000]: Multiple primary key defined
→ Primary Key 제약조건이 2번 들어가서 에러 발생.
CREATE TABLE TITLE_COPY
( COPY_ID int, -- 컬럼 레벨
TITLE_ID int,
STATUS varchar(15) NOT NULL CHECK (STATUS IN ('AVAILABLE', 'DESTROYED', 'RENTED', 'RESERVED')),
FOREIGN KEY (TITLE_ID) REFERENCES TITLE(TITLE_ID), -- 테이블 레벨
PRIMARY KEY (COPY_ID, TITLE_ID)); -- 테이블 레벨
– copy_id 와 title_id 두 컬럼을 묶어서 테이블 레벨로 pk 제약조건을 작성해줌.
→ 자연키 방식.
DESC TITLE_COPY;
✓ 실행 결과
▸ 서브쿼리를 사용한 테이블 생성
create table as
select ...
– 서브쿼리를 사용해서 테이블 생성 시, 서브쿼리의 출력 결과가 새로운 테이블로 복사되어 생성됨.
– 단, 제약조건은 not null 제약조건만 복사됨.
– 테이블 백업 또는 테스트용 테이블 생성 시 주로 활용함.
– 테이블 생성에서 사용되는 서브쿼리의 컬럼 리스트에는 컬럼, 표현식, 함수를 사용할 수 있음.
– 새롭게 생성되는 테이블의 컬럼명은 서브쿼리가 출력해주는 컬럼의 이름값으로 사용하게 됨.
→ 다만 표현식, 함수 경우에는 컬럼명으로는 사용할 수 없는 기호나 공백의 문자가 들어가게 되므로
column alias를 필수로 사용해야함.
EX ) |
CREATE TABLE dept80
AS
SELECT
employee_id,
last_name,
salary * 12 AS annsal,
hire_date
FROM
hr.employees
WHERE
department_id = 80;
DESC dept80;
– 'create table as select' 문법으로 테이블 복사가 가능함.
– 생성된 테이블의 데이터타입과 크기값은 서브쿼리에서 출력에 사용된 테이블의 정보를 사용하여 설정됨.
✓ 실행 결과
SELECT * FROM dept80;
– 서브쿼리로 테이블을 생성하는 경우 테이블구조 뿐 아니라 출력되는 행까지도 복사됨.
✓ 실행 결과
SELECT * FROM information_schema.table_constraints
WHERE constraint_schema = 'shopdb'
AND table_name = 'dept80';
– 다만 제약조건은 NOT NULL을 제외하고는 복사되지 않음.
✓ 실행 결과
📍 테이블 수정 (Alter Table)
– 기존 테이블의 구조를 변형하는데 사용하는 문법.
▸ 컬럼 추가 (ADD)
ALTER TABLE 테이블명
ADD 컬럼명 데이터타입 [DEFAULT] [FIRST / AFTER] [기준 컬럼명]
생성할 위치
– 새로운 컬럼, 제약조건들을 추가할 때 사용하는 절.
– 초기 값은 NULL값이 삽입되어 있고 DEFAULT 값 지정 가능.
– 테이블 생성 후 컬럼 추가 시, 기본적으로 마지막 컬럼으로 추가됨.
EX1 ) 컬럼 추가하기 |
ALTER TABLE dept80
ADD job_id varchar(9);
SELECT * FROM dept80;
– ADD + 컬럼명 + 데이터타입을 입력하자 이에 알맞는 컬럼이 생성됨.
→ 추가된 컬럼은 데이터가 없음.
– 사실상 제일 좋은 건 처음 테이블 생성 시 잘 만드는게 깔끔하고 좋음.
✓ 실행 결과
EX2 ) 컬럼 추가하기 (default값 지정) |
ALTER TABLE dept80
ADD email varchar(30) DEFAULT '미입력';
SELECT * FROM dept80;
– 추가하는 컬럼에 default값이 있는 경우, 초기 값으로 NULL값 대신 default값을 채우게 됨.
✓ 실행 결과
EX3 ) 가장 앞 또는 특정 컬럼 뒤에 컬럼 추가하기 |
ALTER TABLE dept80
ADD emp_number int FIRST;
SELECT * FROM dept80;
– 'int FIRST' 로 인해 emp_number 컬럼이 가장 앞 위치로 생성됨.
✓ 실행 결과
ALTER TABLE dept80
ADD salary int DEFAULT 300 NOT NULL AFTER last_name;
SELECT * FROM dept80;
– salary 컬럼을 추가하는데 int타입이며 default값으로 300을 갖고 제약조건은 not null이며,
'last_name 컬럼 다음' 에 위치함.
✓ 실행 결과
▸ 컬럼 수정 (Modify)
ALTER TABLE 테이블명
MODIFY 컬럼명 [데이터타입] [DEFAULT default값] [NULL / NOT NULL]
– 테이블의 기존 컬럼을 수정하는데 사용하는 문법.
– 데이터타입, 크기, default (기본)값을 수정할 수 있음.
EX1 ) 데이터타입, 크기, default 값 변경하기 |
ALTER TABLE dept80
MODIFY salary bigint;
ALTER TABLE dept80
MODIFY last_name varchar(30) NOT NULL;
ALTER TABLE dept80
MODIFY salary bigint DEFAULT 500 NOT NULL;
DESC dept80;
– 기존의 salary 컬럼은 int타입이였고, 이를 bigint타입으로 수정함.
– last_name 컬럼에는 30byte로 고치고 not null 제약을 거는 걸로 수정함.
– bigint타입의 salary 컬럼의 default 값을 500으로 맞추고 not null 제약을 거는 걸로 수정함.
→ 저장된 default값이 변경되는게 아니라 변경 이후 데이터 삽입 시부터 적용됨.
✓ 실행 결과
EX2 ) 컬럼명 변경 (RENAME) |
ALTER TABLE dept80
RENAME COLUMN hire_date TO start_date;
DESC dept80;
– 기존 컬럼의 hire_date 이름을 다른 이름 start_date로 변경함.
– 되도록 컬럼명을 바꾸기 보다는 Column Alias를 사용하는게 좋음. 뒤의 작업에서 나타나면 또 바꿔줘야해서 번거로움.
✓ 실행 결과
▸ 컬럼 삭제
ATLER TABLE 테이블명
DROP 컬럼명;
– 기존 테이블의 컬럼을 삭제하는 문법.
– 다른 컬럼에 참조를 해주고 있는 제약조건 (foreign key)이 설정된 부모 컬럼인 경우,
제약조건을 먼저 삭제한 뒤 테이블 구조를 변경할 수 있음.
EX ) 컬럼 삭제하기 |
ALTER TABLE dept80
DROP emp_number;
DESC dept80;
– 첫 번째 컬럼에 있던 emp_number 컬럼이 삭제됨.
→ 컬럼의 구조를 통으로 들어내는 것이라 그 안에 저장되어 있던 데이터와 제약조건도 삭제됨.
→ 단, 부모 컬럼 (다른 컬럼이 참조하는 컬럼)일 경우, 제약조건을 먼저 삭제한 뒤 삭제가 가능함.
✓ 실행 결과
▸ 제약조건 추가
– 제약조건을 별도로 추가하는 경우, 테이블 레벨의 제약조건 문법으로 작성함.
1. PRIMARY KEY 추가
ALTER TABLE 테이블명
ADD PRIMARY KEY (제약조건 적용 컬럼명);
ALTER TABLE dept80
ADD PRIMARY KEY(employee_id);
– 기존에 dept80 테이블에는 아무런 제약조건이 없었으나 employee_id 컬럼에 PK와 unique 제약조건이 추가됨.
✓ 실행 결과


2. UNIQUE 추가
ALTER TABLE 테이블명
ADD UNIQUE (제약조건 적용 컬럼);
UPDATE dept80
SET email = NULL;
ALTER TABLE dept80
ADD UNIQUE(email);
DESC dept80;
– 기존 데이터가 있는 경우, 중복값이 있으면 제약조건을 설정할 수 없음.
✓ 실행 결과
3. NOT NULL 추가 ( = 수정)
ALTER TABLE 테이블명
MODIFY 컬럼명 데이터타입 NULL / NOT NULL;
ALTER TABLE dept80
MODIFY annsal double(22,0) NOT NULL;
DESC dept80;
– decimal타입에서 double타입으로 수정.
– not null 제약조건은 테이블 레벨의 문법이 없으므로 컬럼의 정의와 연결되어 수정해야 함.
✓ 실행 결과
4. CHECK 추가
ALTER TABLE 테이블명
ADD CHECK (조건식);
ALTER TABLE dept80
ADD CHECK (salary > 100);
– check 제약조건은 컬럼 레벨과 테이블의 레벨의 제약조건의 형태가 동일함.
– 조건식의 내용에 조건이 적용될 컬럼이 포함되어 있으므로 제약조건이 적용될 컬럼을 별도로 명시하지 않음.
SELECT * FROM information_schema.check_constraints;
– desc 명령어로는 check제약조건을 조회할 수 없음.
– information_schema의 check_constraints 테이블에서 데이터베이스에 적용된 체크 제약조건의 내용을 볼 수 있다.
✓ 실행 결과
5. FOREIGN KEY 추가
ALTER TABLE 테이블명
ADD FOREIGN KEY(참조 컬럼명) REFERENCES 부모테이블명(부모컬럼명);
자식키 부모키
EX ) |
• 새로운 컬럼 생성
ALTER TABLE dept80
ADD mgr_id int DEFAULT 150;
DESC dept80;
– 임의의 컬럼 mgr_id 을 하나 생성해줌. 위치 설정을 따로 하지 않았으므로 가장 마지막에 추가됨.
✓ 실행 결과
SELECT * FROM dept80;
✓ 실행 결과
• 데이터타입 바꾸기
ALTER TABLE dept80
MODIFY mgr_id int UNSIGNED;
– 외래키 제약조건 관계는 데이터타입이 일치해야하므로 데이터타입을 먼저 바꿔줌.
ALTER TABLE dept80
ADD FOREIGN KEY(mgr_id) REFERENCES dept80(employee_d);
-- 자식키 -- 부모키
DESC dept80;
– Key 항목에 MUL이라고 뜨면 외래키가 있다고 생각해도 무방함.
– 부모 컬럼과 자식 컬럼의 데이터타입이 같아 외래키 제약조건이 가능하며 Key 항목을 통해 걸려있음을 확인할 수 있음.
✓ 실행 결과
▸ 제약조건 확인
방법1 ) 제약조건 확인하는 쿼리 작성
SELECT
tc.CONSTRAINT_TYPE,
tc.TABLE_NAME,
kcu.COLUMN_NAME,
kcu.REFERENCED_TABLE_NAME,
kcu.REFERENCED_COLUMN_NAME
FROM
information_schema.TABLE_CONSTRAINTS AS tc
JOIN
information_schema.KEY_COLUMN_USAGE AS kcu
ON
tc.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME
AND
tc.TABLE_SCHEMA = kcu.TABLE_SCHEMA
AND
tc.TABLE_NAME = kcu.TABLE_NAME
WHERE
tc.TABLE_SCHEMA = 'shopdb'
AND
tc.TABLE_NAME = 'dept80';
– 해당 쿼리로 제약조건 확인 가능하지만,
MySQL은 이렇게 확인하는게 너무 복잡하니까 그냥 개발도구 도움 받아서 확인하는게 좋음.
✓ 실행 결과
방법2 ) 워크벤치로 제약조건 확인
▸ 제약조건 삭제
1. PRIMARY KEY 삭제
ALTER TABLE 테이블명
DROP PRIMARY KEY;
– PRIMARY KEY 제약조건의 경우, 제약조건명은 모든 테이블이 PRIMARY KEY로 동일함.
– 다른 외래키의 부모인 상태에서는 바로 제약조건을 제거할 수 없음.
EX ) |
ALTER TABLE dept80
DROP PRIMARY KEY;
2. UNIQUE 삭제
ALTER TABLE 테이블명
DROP INDEX 컬럼명;
– MySQL에서는 고유값을 가진 컬럼에만 UNIQUE 제약조건이 설정됨.
– 컬럼에 설정된 INDEX를 삭제하면 UNIQUE 제약조건이 삭제됨.
→ 그러나 사실상 INDEX는 마음대로 삭제하고 추가하기 난해함.
→ 하나를 삭제하면 INDEX 순서가 바뀌기 때문에 상황에 따라서 기회비용을 따져 결정해야 함.
→ INDEX에 대한 자세한 내용은 ORACLE에서 배움.
EX ) |
ALTER TABLE dept80
DROP INDEX email;
DESC dept80;
✓ 실행 결과
3. NOT NULL 삭제
ALTER TABLE 테이블명
MODIFY 컬럼명 데이터타입 NULL / NOT NULL;
– NOT NULL 제약조건은 컬럼의 속성값으로 컬럼의 정의를 수정하여 사용여부를 정할 수 있음.
EX ) |
ALTER TABLE dept80
MODIFY last_name varchar(30) NULL;
DESC dept80;
✓ 실행 결과
4. FOREIGN KEY 삭제
ALTER TABLE 테이블명
DROP FOREIGN KEY 제약조건명;
– FOREIGN KEY 제약조건 이름을 알아야 하므로 먼저 제약조건 이름을 조회한 뒤 삭제함.
EX ) |
1. 제약조건 정보 조회
• 워크벤치로 조회
– 삭제하려는 제약조건의 이름을 입력해야 하므로 워크벤치로 이름을 조회함.
– 제약조건 적용 시 별도의 이름을 지정하지 않는 경우 데이터베이스에서 자동으로 이름을 설정해줌.
• 제약조건 조회 쿼리
SELECT * FROM information_schema.table_constraints
WHERE constraint_schema = 'shopdb'
AND table_name = 'dept80';
✓ 실행 결과
2. 제약조건 삭제
ALTER TABLE dept80
DROP FOREIGN KEY dept80_ibfk_1;
SELECT * FROM information_schema.table_constraints
WHERE constraint_schema = 'shopdb'
AND table_name = 'dept80';
✓ 실행 결과
5. CHECK 삭제
ALTER TABLE 테이블명
DROP CHECK 제약조건명;
– FOREIGN KEY 와 마찬가지로 제약조건 이름을 알아야 하므로 먼저 제약조건 이름을 조회한 뒤 삭제함.
EX ) |
1. 제약조건 정보 조회
SELECT * FROM information_schema.check_constraints;
– check 제약조건은 mysql8 부터 사용가능한 제약조건으로 기존 제약조건을 조회하는 방법으로는 볼 수 없음.
– 위와 같이 별도의 check_constraints 테이블에서 check제약조건을 확인할 수 있음.
✓ 실행 결과
2. 제약조건 삭제
ALTER TABLE dept80
DROP CHECK dept80_chk_1;
SELECT * FROM information_schema.check_constraints;
– 삭제하려는 check 제약조건의 이름값을 입력하고 다시 조회함.
✓ 실행 결과
📍 테이블 삭제 (Drop Table)
DROP TABLE 테이블명;
– 기존 테이블을 삭제할 때 사용하는 문법.
– 다른 테이블에서 참조하는 컬럼이 있는 테이블은 DROP 할 수 없음.
→ 참조하는 외래키들을 다 제거한다면 DROP 가능.
EX ) |
DROP TABLE copy_emp;
✓ 실행 결과

DROP TABLE departments;
– SQL Error [3730] [HY000]: Cannot drop table 'departments' referenced by a foreign key constraint
'employees_departments_department_id' on table 'employees' 에러 발생.
– 다른 테이블에서 참조하는 컬럼이 있는 테이블이므로 삭제 불가.
📍 연습 문제 1
▸ 테이블 생성
1. major table
• 테이블 생성
CREATE TABLE major
(major_id int PRIMARY KEY AUTO_INCREMENT,
major_name varchar(50) NOT NULL);
• 데이터 입력
INSERT INTO major (major_id, major_name)
VALUES
(1, "컴퓨터공학"),
(2, "수학과"),
(3, "영어영문학");
SELECT * FROM major;
✓ 실행 결과
2. student table
• 테이블 생성
CREATE TABLE student
(student_id int PRIMARY KEY AUTO_INCREMENT,
name varchar(50) NOT NULL,
birthdate date NOT NULL,
major_id int,
FOREIGN KEY(major_id) REFERENCES major(major_id));
• 데이터 입력
INSERT INTO student (name, birthdate, major_id)
VALUES
("김철수", "1999-05-12", 1),
("이영희", "2000-08-25", 2),
("박민수", "1999-11-30", 1),
("최지은", "2001-02-19", 3);
– Auto_increment가 적용된 컬럼은 뺀 나머지 컬럼을 명시하고 데이터를 입력하면
Auto_increment에 의해 해당 컬럼은 자동으로 1씩 증가함.
SELECT * FROM student;
✓ 실행 결과
3. professor table
• 테이블 생성
CREATE TABLE professor
( professor_id int PRIMARY KEY AUTO_INCREMENT,
name varchar(50) NOT NULL);
• 데이터 입력
INSERT INTO professor (name)
VALUES
("김도현"),
("이윤미"),
("박상준");
SELECT * FROM professor;
✓ 실행 결과
4. courses table
• 테이블 생성
CREATE TABLE courses
( course_id int PRIMARY KEY AUTO_INCREMENT,
course_name varchar(50) NOT NULL,
professor_id int,
FOREIGN KEY(professor_id) REFERENCES professor(professor_id));
• 데이터 입력
INSERT INTO courses (course_name, professor_id)
VALUES
("자료구조", 1),
("미적분학", 2),
("영문학개론", 3),
("프로그래밍", 1);
SELECT * FROM courses;
✓ 실행 결과
5. grades table
• 테이블 생성
CREATE TABLE grades
( grade_id int PRIMARY KEY AUTO_INCREMENT,
student_id int,
course_id int,
grade float NOT NULL,
FOREIGN key(student_id) REFERENCES student(student_id),
FOREIGN key(course_id) REFERENCES courses(course_id));
• 데이터 입력
INSERT INTO grades (student_id, course_id, grade)
VALUES
(1, 1, 85),
(2, 2, 90),
(3, 1, 78),
(4, 3, 92);
SELECT * FROM grades;
✓ 실행 결과
▸ UPDATE 구문 작성
Q1. 학생 테이블에서 학생 이름이 '김철수'인 학생의 전공을 '영어영문학'으로 변경하기.
UPDATE major SET major_name = "영어영문학"
WHERE major_id = (SELECT major_id
FROM student
WHERE name = "김철수");
-- 확인
SELECT s.name, m.major_name
FROM major m JOIN student s
ON m.major_id = s.major_id;
✓ 실행 결과
Q2. 성적 테이블에서 학생 아이디가 3인 학생의 성적을 10점 올리기.
UPDATE grades SET grade = (grade+10)
WHERE student_id = 3;
-- 확인
SELECT student_id, grade
FROM grades
WHERE student_id = 3;
✓ 실행 결과

▸ DELETE 구문 작성
Q. 과목 테이블에서 교수 아이디가 2인 교수가 가르치는 과목을 모두 삭제하기.
– 과목 테이블에서 교수 아이디가 2인 교수가 가르치는 과목을 삭제하려 했더니 안됨.
– FOREIGN KEY (`course_id`) REFERENCES `courses` (`course_id`)) 에러 발생.
→ course 테이블의 course_id 컬럼이 부모 컬럼이라 삭제 안됨.
→ courses 테이블의 course_id 컬럼을 부모로 가지고 있는 자식컬럼을 먼저 삭제해야 함.
→ 찾아보니 grades 테이블의 course_id가 자식컬럼.
→ grades 테이블의 course_id 컬럼의 교수 아이디가 2인걸 먼저 삭제.
– 관련 작업이 많은 경우 외래키 제약조건에 ON DELETE CASCADE를 사용하는 것도 방법.
• 자식컬럼 삭제
DELETE FROM grades
WHERE course_id = 2;
• 교수 아이디가 2인 교수가 가르치는 과목 삭제
DELETE FROM courses
WHERE professor_id = 2;
-- 확인
SELECT * FROM courses;
✓ 실행 결과
▸ ALTER TABLE 구문
Q1. 학생 테이블에서 학생의 이름 컬럼의 데이터 타입을 VARCHAR(100)으로 변경하기.
ALTER TABLE student
MODIFY name varchar(100);
-- 확인
DESC student;
✓ 실행 결과
Q2. 교수 테이블에 이메일 컬럼 추가하기.
이메일 컬럼은 VARCHAR(100)이며, 고유한 값을 가져야 함.
ALTER TABLE professor
ADD email varchar(100) DEFAULT '미입력';
-- 확인
SELECT * FROM professor;
✓ 실행 결과
Q3. 과목 테이블에서 교수 아이디(professor_id)에 대한 외래 키 제약조건 삭제하기.
(외래 키 제약조건 이름은 'fk_courses_professors' 라고 가정.)
ALTER TABLE courses
DROP FOREIGN KEY fk_courses_professors;
– 위의 DELETE구문에서 외래키를 삭제했으므로 사실상 걸려있는 외래키가 없음.
→ 실행하면 당연히 에러 발생. 쿼리만 알아두기.
▸ VIEW 생성 및 수정
– courses, grades, majors, students 테이블 JOIN 사용.
Q1. 학생의 이름, 전공 이름, 각 학생의 수강한 과목 이름과 성적을 포함하는 뷰 생성하기.
뷰의 이름은 'student_grades_major'로 지정함.
CREATE VIEW student_grades_major AS
SELECT s.name, m.major_name, c.course_name ,g.grade
FROM student s
JOIN major m ON s.major_id = m.major_id
JOIN grades g ON s.student_id = g.student_id
JOIN courses c ON g.course_id = c.course_id;
-- 확인
SELECT * FROM student_grades_major
✓ 실행 결과
Q2. 각 과목별로 평균 성적과 학과 이름을 포함하는 뷰 생성하기.
뷰의 이름은 'course_avg_grade_major'로 지정함.
CREATE VIEW course_avg_grade_major AS
SELECT m.major_name, c.course_name, AVG(g.grade)
FROM student s
JOIN major m ON s.major_id = m.major_id
JOIN grades g ON s.student_id = g.student_id
JOIN courses c ON g.course_id = c.course_id
GROUP BY m.major_name, c.course_name;
-- 확인
SELECT * FROM course_avg_grade_major ;
✓ 실행 결과
📍 연습 문제 2
▸ 도서 대여
• 데이터베이스 생성
CREATE DATABASE book_borrow;
SHOW DATABASES;
USE book_borrow;
• 테이블 생성
1. User 테이블
CREATE TABLE User
( user_id int PRIMARY KEY AUTO_INCREMENT,
name varchar(50) NOT NULL,
email varchar(100) NOT NULL UNIQUE,
phone_number varchar(15) NOT NULL UNIQUE,
address varchar(200) );
2. Category 테이블
CREATE TABLE Category
( category_id int PRIMARY KEY AUTO_INCREMENT,
category_name varchar(50) NOT NULL UNIQUE );
3. BookLocation 테이블
CREATE TABLE BookLocation
( location_id int PRIMARY KEY AUTO_INCREMENT,
location varchar(100) NOT NULL UNIQUE );
4. Book 테이블
CREATE TABLE Book
( book_id int PRIMARY KEY AUTO_INCREMENT,
title varchar(100) NOT NULL,
author varchar(100) NOT NULL,
category_id int,
location_id int,
FOREIGN KEY (category_id) REFERENCES Category(category_id),
FOREIGN KEY (location_id) REFERENCES BookLocation(location_id) );
5. BorrowRecord 테이블
CREATE TABLE BorrowRecord
( record_id int PRIMARY KEY AUTO_INCREMENT,
user_id int,
book_id int,
borrow_date date NOT NULL,
due_date date NOT NULL,
return_date date,
FOREIGN KEY (user_id) REFERENCES User(user_id),
FOREIGN KEY (book_id) REFERENCES Book(book_id) );
• 데이터 입력
1.
INSERT INTO User (name, email, phone_number, address)
VALUES
('김영희', 'younghee@example.com', '010-1234-5678', '서울시 마포구 상암동'),
('이철수', 'cheolsu@example.com', '010-2345-6789', '서울시 강남구 역삼동'),
('박지영', 'jiyoung@example.com', '010-3456-7890', '서울시 송파구 잠실동'),
('최민수', 'minsu@example.com', '010-4567-8901', '인천시 남동구 구월동'),
('김수진', 'sujin@example.com', '010-5678-9012', '서울시 관악구 신림동'),
('황예원', 'yewon@example.com', '010-6789-0123', '서울시 중구 명동'),
('이현우', 'hyunwoo@example.com', '010-7890-1234', '부산시 해운대구 중동'),
('박성민', 'sungmin@example.com', '010-8901-2345', '서울시 서초구 반포동'),
('한지민', 'jimin@example.com', '010-9012-3456', '대전시 유성구 봉명동'),
('장현준', 'hyunjoon@example.com', '010-0123-4567', '울산시 남구 신정동');
2.
INSERT INTO Category (category_name)
VALUES
('소설'),
('에세이'),
('역사'),
('과학'),
('인문학'),
('경제'),
('예술'),
('컴퓨터/IT'),
('여행'),
('자기계발');
3.
INSERT INTO BookLocation (location)
VALUES
('1층 A구역'),
('1층 B구역'),
('2층 A구역'),
('2층 B구역'),
('3층 A구역'),
('3층 B구역'),
('4층 A구역'),
('4층 B구역'),
('5층 A구역'),
('5층 B구역');
4.
INSERT INTO Book (title, author, category_id, location_id)
VALUES
('자존감 수업', '윤홍균', 10, 1),
('해리포터와 마법사의 돌', 'J.K. 롤링', 1, 2),
('컴퓨터과학이 여는 세계', '김진아', 8, 3),
('세계사를 만든 역사', '안창호', 3, 4),
('달러구트 꿈 백화점', '이미예', 1, 5),
('우리가 빛의 속도로 갈 수 없다면', '김초엽', 5, 6),
('시간의 역사', '스티븐 호킹', 4, 7),
('수학이 알려주는 거짓말의 법칙', '조던 엘렌버그', 4, 8),
('미술관에 간 작가들', '이경록', 7, 9),
('누구나 쉽게 익히는 파이썬', '서진수', 8, 10),
('미래의 선택', '앨빈 토플러', 5, 2),
('인공지능의 시대', '김영성', 8, 4),
('심리학의 이해', '이현진', 5, 3),
('코딩 철학', '정용준', 8, 6),
('탈무드의 지혜', '류시화', 5, 7),
('세계미술사', '김영미', 7, 5),
('데이터 과학', '이승준', 8, 6),
('역사 속의 거짓말', '박종석', 3, 1),
('프랑스 여행기', '김민아', 9, 9),
('영어 회화의 비밀', '최은영', 10, 10);
-- 5.
INSERT INTO BorrowRecord (user_id, book_id, borrow_date, due_date, return_date)
VALUES
(1, 1, '2023-03-01', '2023-03-15', '2023-03-13'),
(2, 2, '2023-03-05', '2023-03-19', '2023-03-18'),
(3, 3, '2023-03-10', '2023-03-24', '2023-03-22'),
(4, 4, '2023-03-15', '2023-03-29', '2023-03-28'),
(5, 5, '2023-03-20', '2023-04-03', '2023-04-02'),
(6, 6, '2023-03-25', '2023-04-08', NULL),
(7, 7, '2023-03-30', '2023-04-13', NULL),
(8, 8, '2023-04-04', '2023-04-18', NULL),
(9, 9, '2023-04-09', '2023-04-23', NULL),
(10, 10, '2023-04-14', '2023-04-28', NULL),
(1, 6, '2023-04-16', '2023-04-30', NULL),
(2, 7, '2023-04-11', '2023-04-25', NULL),
(3, 8, '2023-04-06', '2023-04-20', NULL),
(4, 9, '2023-04-01', '2023-04-15', '2023-04-14'),
(5, 10, '2023-03-27', '2023-04-10', '2023-04-09'),
(6, 1, '2023-03-22', '2023-04-05', '2023-04-04'),
(7, 2, '2023-03-17', '2023-03-31', '2023-03-30'),
(8, 3, '2023-03-12', '2023-03-26', '2023-03-25'),
(9, 4, '2023-03-07', '2023-03-21', '2023-03-20'),
(10, 5, '2023-03-02', '2023-03-16', '2023-03-15'),
(6, 16, '2023-01-30', '2023-02-13', '2023-02-12'),
(7, 17, '2023-01-25', '2023-02-08', '2023-02-07'),
(8, 18, '2023-01-20', '2023-02-03', '2023-02-02'),
(9, 19, '2023-01-15', '2023-01-29', '2023-01-28'),
(10, 20, '2023-01-10', '2023-01-24', '2023-01-23'),
(1, 11, '2023-04-15', '2023-04-29', NULL),
(2, 12, '2023-04-10', '2023-04-24', NULL),
(3, 13, '2023-04-05', '2023-04-19', NULL),
(4, 14, '2023-04-01', '2023-04-15', '2023-04-14'),
(5, 15, '2023-03-26', '2023-04-09', '2023-04-08'),
(6, 16, '2023-03-21', '2023-04-04', '2023-04-03'),
(7, 17, '2023-03-16', '2023-03-30', '2023-03-29'),
(8, 18, '2023-03-11', '2023-03-25', '2023-03-24'),
(9, 19, '2023-03-06', '2023-03-20', '2023-03-19'),
(10, 20, '2023-03-01', '2023-03-15', '2023-03-14'),
(1, 11, '2023-02-24', '2023-03-10', '2023-03-09'),
(2, 12, '2023-02-19', '2023-03-05', '2023-03-04'),
(3, 13, '2023-02-14', '2023-02-28', '2023-02-27'),
(4, 14, '2023-02-09', '2023-02-23', '2023-02-22'),
(5, 15, '2023-02-04', '2023-02-18', '2023-02-17'),
(1, 11, '2023-01-05', '2023-01-19', '2023-01-18'),
(2, 12, '2022-12-31', '2023-01-14', '2023-01-13'),
(3, 13, '2022-12-26', '2023-01-09', '2023-01-08'),
(4, 14, '2022-12-21', '2023-01-04', '2023-01-03'),
(5, 15, '2022-12-16', '2022-12-30', '2022-12-29'),
(6, 16, '2022-12-11', '2022-12-25', '2022-12-24'),
(7, 17, '2022-12-06', '2022-12-20', '2022-12-19'),
(8, 18, '2022-12-01', '2022-12-15', '2022-12-14'),
(9, 19, '2022-11-26', '2022-12-10', '2022-12-09'),
(10, 20, '2022-11-21', '2022-12-05', '2022-12-04');
• View 생성
1. 현재 대출 중인 도서의 정보를 출력하는 currently_borrowed_books 뷰 생성하기.
– 반납되지 않은 도서는 대출 중으로 볼 수 있음.
– borrower는 책 빌려간 사람 이름.
CREATE VIEW currently_borrowed_books AS
SELECT b.book_id, b.title, b.author, br.user_id, name borrower, borrow_date, due_date
FROM Book b JOIN BorrowRecord br JOIN User u
ON b.book_id = br.book_id && br.user_id = u.user_id;
-- 확인
SELECT * FROM currently_borrowed_books;
✓ 실행 결과
2. 연체 도서 목록 출력하는 overdue_books 뷰 생성.
– 오늘 (2023-04-17) 기준 연체된 도서 출력.
– borrower는 책 빌려간 사람의 이름.
CREATE VIEW overdue_books AS
SELECT b.book_id, title, author, u.user_id, name borrower, borrow_date, due_date
FROM Book b JOIN BorrowRecord br JOIN User u
ON b.book_id = br.book_id && br.user_id = u.user_id
WHERE '2023-04-17' > due_date;
-- 확인
SELECT * FROM overdue_books;
✓ 실행 결과
3. 도서별 대출 횟수를 출력하는 book_borrow_count 뷰 생성
– borrow_count는 대출 횟수 값.
CREATE VIEW book_borrow_count AS
SELECT br.book_id, title, count(b.book_id) borrow_count
FROM BorrowRecord br JOIN book b
ON br.book_id = b.book_id
GROUP BY b.book_id;
-- 확인
SELECT * FROM book_borrow_count
✓ 실행 결과
4. 사용자 별 대출 횟수를 출력하는 user_borrow_count 뷰 생성하기.
– borrow_count는 대출 횟수 값.
CREATE VIEW user_borrow_count AS
SELECT u.user_id, name, email, count(u.user_id) borrow_count
FROM USER u JOIN BorrowRecord br
ON u.user_id = br.user_id
GROUP BY u.user_id;
-- 확인
SELECT * FROM user_borrow_count;
✓ 실행 결과
• 백업 스크립트
mysqldump -u 계정명 -p 백업DB > 백업파일명.sql
mysqldump -u root -p book_barrow > backup.sql
– 다음 명령어를 터미널에서 입력.
– 백업 스크립트 파일은 접속 중인 터미널 경로에 생성됨.
– 백업 파일의 경로를 절대경로로 작성하는 경우, 현재 접속 위치와는 상관없이 생성됨.
→ 절대경로는 파일명 앞에 작성해줌.
💡 원하는 폴더 위치가 있을 경우, 해당 폴더 위치의 주소창에 cmd를 검색하면 해당 위치로 경로가 지정됨.
'DB > MySQL' 카테고리의 다른 글
데이터정의어 (DDL) — 연습 문제 (0) | 2023.04.18 |
---|---|
데이터정의어 (DDL) — View (0) | 2023.04.05 |
트랜잭션제어어 (TCL) (0) | 2023.03.21 |
데이터 조작어 (DML) (0) | 2023.03.20 |
서브쿼리 (SubQuery) (0) | 2023.03.14 |
- Total
- Today
- Yesterday
- DB
- null
- 출력문
- 숫자형
- 데이터타입
- 논리형
- JSTL
- Java
- jsp
- 업캐스팅
- Git
- 다형성
- 단일행함수
- github
- 문자형
- mysql
- Object
- 오버라이딩
- Dao
- 주석문
- 내장객체
- Method
- 제어문
- 인자
- 원격저장소
- model2
- javascript
- gitbash
- 매개변수
- 로컬저장소
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |