오늘 내가 배운 것
1. 제약조건
2. 테이블 만들기
- 2-1. Query문을 이용한 테이블 만들기
- 2-2. Sequlize - class를 이용한 테이블 만들기
3. 외래키 지정하기 (FK)
- Query문을 이용한 제약사항 확인하기
- 3-1. Query문을 이용한 외래키 (foreign key) 지정하기
- 3-2. Query문을 이용한 외래키 (foreign key) 삭제하기
- 3-3. Query문을 이용한 외래키 (foreign key) ON DELETE 옵션
- 3-4. sequelize에서 외래키(foreign key) 지정하기
4. 테이블 JOIN 하기
- 4-1. Query문을 이용한 JOIN
- 4-2. sequelize를 이용한 JOIN
1. MySQL 제약조건
테이블에 데이터를 저장할 때 데이터의 정확성, 일관성, 유효성을 지키기 위해서(데이터의 무결성) 일정한 규칙을 정하기 위해 사용하는 방법이다.
NOT NULL
- NULL값을 가질 수 없다.
- 설정된 필드는 무조건 데이터가 있어야 함.
기본키 (Primary key)
- 중복되지 않는 고윳값
- Null 허용하지 않음
- 테이블당 하나의 기본키만 지정 가능
고유키 (Unique)
- 중복되지 않는 고윳값
- Null 가능
외래키 (foreign key)
- 테이블을 다른 테이블과 연결해 주는 역할
- 기준 테이블의 내용을 참조해서 레코드가 입력
- FOREIGN KEY를 설정할 때 참조되는 테이블의 필드는 반드시 UNIQUE나 PRIMARY KEY가 설정되어 있어야 함.
1:N 관계
1 - 부모테이블 [PK]
N - 자식테이블 [FK]
자식테이블에는 부모의 고유식별자(PK) 값을 받아야 한다.
EX) 게시판과 댓글의 관계
하나의 게시판(부모)에 여러 개의 댓글(자식)을 만들 수 있다.
댓글 테이블에는 게시판 테이블의 PK를 FK로 받는다.
자식테이블에게 부모테이블의 고유 식별자 필드를 하나 추가한다.
2. 테이블 만들기
2-1. Query문을 이용한 테이블 만들기
CREATE TABLE `user` (
userid VARCHAR(30) PRIMARY KEY,
userpw VARCHAR(64) NOT NULL,
username VARCHAR(20)
)
CREATE TABLE `Board` (
id INT PRIMARY KEY AUTO_INCREMENT,
subject VARCHAR(100) NOT NULL,
content TEXT NOT NULL,
userid VARCHAR(30) NOT NULL,
register_data datetime default now()
hit INT default 0
)
2-2. sequlize - class를 이용한 테이블 만들기
2-2-1. User
module.exports = (sequelize, Sequelize) =>{
class User extends Sequelize.Model {
static initialize(){
return this.init({
userid:{
type:Sequelize.STRING(30),
primaryKey:true,
},
userpw:{
type: Sequelize.STRING(64),
allowNull: false,
},
username:{
type: Sequelize.STRING(20),
allowNull:false
},
},{
sequelize,
})
}
//fk설정하기
static associate(models){
//1:다 관계에서 부모인 user는 많이 줄 것이다라는 뜻으로 생각하면 된다.
//hasMany의 ()안에는 sql에서 REFERENCES User(userid) 부분과 같다
this.hasMany(models.Board, {
foreignKey:"userid"
})
}
}
User.initialize()
return User
}
2-2-2. Board
module.exports = (sequelize, Sequelize) =>{
class Board extends Sequelize.Model {
static initialize(){
return this.init({
subject:{
type: Sequelize.STRING(100),
allowNull: false,
},
content:{
type: Sequelize.TEXT,
allowNull:false
},
registerDate:{
type: Sequelize.DATE,
allowNull:false,
defaultValue : Sequelize.fn("now"),
},
hit:{
type:Sequelize.INTEGER,
defaultValue:0,
},
userid:{
type:Sequelize.STRING(100),
allowNull:true,
},
},{
sequelize,
})
}
//fk설정하기
static associate(models){
this.belongsTo(models.User, {
foreignKey:"userid"
})
}
}
Board.initialize()
return Board
}
Model.init()와 sequelize.define()는 같은 역할이다.
Mode.init함수 안에는 2가지의 인자값이 필요하다.
2가지의 인자값은 객체형태를 이루고, 1번 인자값에는 생성할 column의 속성을 넣어주고,
2번 인자값에는 Sequelize 생성자에 제공되는 기본 정의 옵션을 넣어준다.
3. 외래키 지정하기 (Foreign Key)
- Query문을 이용한 제약사항 확인하기
-- database 안에 table을 확인할 때 쓸 수 있다.
SELECT * FROM [database명].[table명]
-- information_schema 테이블의 모든 정보가 담겨있다. WHERE절을 붙여서 부분선택 가능
SELECT * FROM information_schema.table_constraints
WHERE TABLE_SCHEMA = "samples";
- WHERE 절 조건을 더 세분화해서 보고 싶은 영역만 확인하기.
3-1. Query문을 이용한 외래키 (foreign key) 지정하기
-- 게시판
-- 부모테이블 : User, 자식테이블 : Board
ALTER TABLE `Board` -- 자식테이블
ADD CONSTRAINT fk_board_userid -- fk 삭제할 때 이용한다. fk_board_userid는 변수명 같은 느낌(제약명)
FOREIGN KEY(userid) -- 자식테이블에서 부모의 식별자를 담는 필드명(자식 테이블의 외래키)
REFERENCES User(userid)
-- ON DELETE : 옵션... 밑에 따로 서술
-- ON UPDATE : 옵션... 밑에 따로 서술
3-2. Query문을 이용한 외래키 (foreign key) 삭제하기
- 외래키 삭제
ALTER TABLE [테이블명] DROP CONSTRAINT [제약명]
ALTER TABLE `Board` DROP CONSTRAINT fk_board_userid;
3-3. Query문을 이용한 외래키 (foreign key) ON DELETE 옵션
외래키 지정 시에 ON DELETE를 같이 작성하여 준다.
- ON DELETE CASCADE
- ON DELETE SET NULL
- ON DELETE RESTRICT
ALTER TABLE `Board`
ADD CONSTRAINT fk_board_userid
FOREIGN KEY(userid)
REFERENCES User(userid)
ON DELETE CASCADE || SET NULL || RESTRICT
상황 1 : 제약사항은 테이블을 만들 때 구상해서 미리 설정해야 한다.
-- userid 변경하기
UPDATE Board SET userid = "admin2" WHERE id=6;
user테이블의 row는 2개지만 board의 userid의 내용이 3가지여서 제약사항을 걸면 에러가 발생한다..
결론 :
제약사항은 테이블 안에 레코드가 생성되기 전에 제약사항을 걸어줘야 한다. 그래서 테이블을 잘 구상하는 것이 중요하다.
상황 2 : ON DELETE CASCADE
부모테이블(User)에서 user 1개를 지우기
결론:
제약 조건중 'ON DELETE CASCADE'를 사용하게 되면 부모테이블의 내용을 지우면 자식 테이블 데이터에 영향을 준다.
상황 3 : ON DELETE RESTRICT
자식 테이블에 부모 테이블과 관련된 내용이 있을 때 부모 테이블의 내용을 지울 수 없게 한다.
상황 4 : 상황 4 : ON DELETE SET NULL
자식테이블에서 fk가 NOT NULL이면 안됨
부모의 데이터가 지워져도 자식의 데이터를 지우지 않아야 하는 상황이 있다. (ex: 리뷰...)
부모 데이터(pk)를 지우면 자식테이블에 fk값에 NULL이 기입된 상태로 데이터가 남아 있다.
3-4. sequelize에서 외래키(foreign key) 지정하기
- user.model.js (부모테이블)
static associate(models){
this.hasMany(models.Board, {
foreignKey:"userid"
})
}
- board.model.js (자식테이블)
static associate(models){
this.belongsTo(models.User, {
foreignKey:"userid"
})
}
위에 함수들을 실행하면 지정이 된다.
const { models } = sequelize
// 방법1. 하나씩 다 불러서 실행한다.
// models.Board.associate(models)
// models.User.associate(models)
// 방법2. for-in 반복문을 이용하여 실행
for (const key in models) {
if (typeof models[key].associate !== "function") continue
models[key].associate(models)
}
4. 테이블 JOIN 하기
4-1. Query문을 이용한 JOIN
userid 대신 username을 띄우고 싶은 상황이라면?
SELECT
-- * 로 지정해서 보는 것 보다는 필요한 내용을 보는 것이 낫다.
A.id,
A.subject,
A.register,
A.hit,
A.userid,
B.username
FROM Board as A -- board를 잠깐 변수A로 만든다..(DB에서 바뀌는 것이 아니라 query문 안에서만..)
JOIN User as B
ON A.userid = B.userid -- 두개의 테이블 내용중 똑같은 것이 있어야한다.
JOIN의 방법 중에는 LEFT OUTER, RIGHT OUTER 등등 있지만 나중에 알아볼 예정
기본 JOIN 먼저 하자... (INNER JOIN)
4-2. sequelize를 이용한 JOIN
sequelize를 이용한 방법은 3-4에서 했었던 FK가 잘 설정되어 있으면 문법 자체는 간단하다.
const board = await Board.findAll({
raw:true, // findAll하면 내역이 많은데 그중 값만 보고 싶을 때 사용
nest:true, // 결과에 User를 객체로 따로 뽑아줌..
include:[{model:User}] // join문..
})
Board를 다 찾는데, 거기에서 User을 Join 해서 보여주겠다는 의미이다.
'시작 > TIL(Today I Learned)' 카테고리의 다른 글
230116 - JavaScript - Sequelize을 이용한 CRUD (0) | 2023.01.17 |
---|---|
230113 - Javascript - Sequelize, ERD 활용 페어코딩 (0) | 2023.01.16 |
230111 - JavaScript - 정적메서드와 접근제어자 Private, Sequelize (0) | 2023.01.11 |
230110 - JavaScript - NodeJS, TDD, ORM, Sequelize 모듈 (0) | 2023.01.10 |
230109 - JavaScript - class 클래스와 상속 (0) | 2023.01.09 |