Theme. JDBC(Java DataBase Connectivity)란?

 

RDBMS(MySql, Oracle 등) 또는 DBMS에서 작성된 sql문을 실행함으로써 DB에 접근할 수 있는 것은 누구나 알고 있다.

MySql을 예로 들자면,  MySql Workbench에서 sql문을 작성하면서 MySql과 연결/인증, 문장실행, 결과패치 등을 할 수 있다.

이는 다시 말하면, sql문을 작성할 줄 알면 DB에 접근할 수 있다는 것이다.

물론, sql문을 작성할 줄 알아야만 DB에 접근할 수 있는 것은 아니다.

예를 들어, 개발자가 만든 UI를 이용하는 client는 sql문을 작성할 줄도 모르고, 작성해야할 이유도 없을 것이다.

client가 회원목록에서 어떤 회원에 대한 정보를 달라고 하면, 해당 UI를 통해 sql문이 작성되도록 만들면 되기 때문이다. 

Java 프로그래머로서 DB를 이용하려는 사용자의 요구에 부응하는 sql문을 작성해주고, 이를 실행시켜주면 될 것이다.

 

client의 요구를 처리해줄 수 있는 sql문이 작성이 되고, 작성된 sql문과 DB를 연결하기 위해 필요한 것은 DB API이다. 

이때, DB API에 대해 고려해야할 사항이 있다. MySql, Oracle과 같은 RDBMS들이 모두 같은 메서드, 문법을 사용하지 않는다는 것이다. 이로 인해 sql문을 각각에 연결하기 위 DB API가 모두 달라야 한다.

똑같은 sql문을 실행한다고 해도 어떤 (R)DBMS를 쓰냐에 따라 DB API가 달라지게 되고 이는 굉장히 불편할 것이다. DBMS가 바뀌면 새로운 DBMS에 연결하기 위한 DB API에 대해 알아야 하기 때문이다.

 

이때 등장한 것이 바로 "JDBC"이다. RDMBS에 연결하기 위한 모든 코드들은 다 단일화된 JDBC안에 모여있다고 이해하면 쉽다. 이를 통해 연결하고자 하는 RDBMS에 따라 DB API에 대해 알아야 할 필요가 없다. 이제 각각의 DB API들은 JDBC의 Driver가 된다.(JDBC Driver)

 

Theme. JDBC 사용방법

기본적인 코드는 아래의 "순서대로" 사용된다.

1. 드라이버 로드

2. 연결 생성

3. 문장(sql문) 실행

4. 결과집합 사용

 

각각에 대해서 설명하기 전에,

JDBC를 사용하는 과정을 간단하게 설명하자면, UI를 만들고, UI를 통해 사용자의 요구를 파악하며, 그 요구에 따라 sql문을 작성하고 실행하여 DB를 사용하는 것이다. 아래 그림을 살펴보자.

다시 돌아와서 기본적인 코드들을 작성해보면,

1. JDBC 드라이버 로드하기

MySql을 사용하는 경우에는 다음과 같이 작성하면 된다.

Class.forName("com.mysql.cj.jdbc.Driver");

이때, 로드한다는 것의 의미는 클래스를 객체화한다는 의미이다.

그 결과 메모리에 드라이버가 올라가게 될 것이다.

 

2. 연결 생성하기

연결 객체를 얻는 것이다.

Connection conn = DriverManager.getConnection(url, user, password);

예를들면, Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "ABC", "1111");

 

3. sql문 실행 도구 생성하기

Statement st = con.createStatement();

이를 

PreparedStatement psmt = conn.prepareStatement(sql문); 으로 사용할 수 있다.(이 방법으로 코드를 작성하였다)

 

4. 실행 결과를 저장하는 객체 생성하기(결과 집합을 패치)

ResultSet rs = st.executeQuery(sql); 

이는 select, insert, update, delete 등에 따라 사용하는 메서드가 다르다.

// psmt.excuteQuery() : select

// psmt.excuteUpdate() : insert, update, delete ..

 

그림을 통해 과정을 살펴보자.

0. JDBC 사용 전

 

1. 드라이버 로드

Class.forName("com.mysql.cj.jdbc.Driver");

2. 연결 생성

Connection conn = DriverManager.getConnection(url, user, password);

 

 

3. 실행 도구 생성

PreparedStatement psmt = conn.prepareStatement(sql문);

sql문이 실행된다.

 

4. 결과 담을 객체 생성(결과 집합 생성)

ResultSet rs = st.executeQuery(sql); 

sql문이 실행되고 나면 다음과 같은 결과 집합(테이블)이 생성된다. 이는 레코드의 집합이다.

 

서버에서는 결과집합을 사용자에게 한번에 다 돌려주는 것이 아니다. 

결과 집합은 서버에 있는 채로, client는 레코드 단위로 하나씩 받게 된다. 이때 레코드를 가리키는 위의 화살표가 커서이다.

처음 커서는 Before of File에 위치하게 된다.

이때, rs.next(); 가 실행되면, 아래와 같이 커서가 이동하면서 그 레코드를 client에게 전달하게 된다.

이 커서가 End of File에 위치하게 되면 결과 집합을 모두 읽은 것이다.

 

Theme. Insert, select, update, delete문 작성하기

1. DBConnection.java 파일

 - 드라이버를 로드하는 것과 연결 생성하는 과정을 DBConnection이라는 클래스 안에 메서드로 만들어 두었다.

 - initConnection()이라는 메서드를 만들어서 드라이버를 로드한다.

 - getConnection()이라는 메서드를 만들어서 연결을 생성한다.

 

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
31
32
33
34
35
36
37
38
package db;
 
import java.sql.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
 
public class DBConnection {
 
    public static void initConnection() { // static이니까 언제든지 불러쓸 수 있다.
        
        try {
            Class.forName("com.mysql.cj.jdbc.Driver"); // 드라이버 로드하기
            System.out.println("Driver Loading Success");
        } catch (ClassNotFoundException e) {            
            System.out.println("DB Driver를 찾지 못했습니다");
            e.printStackTrace();
        }    
        
    }
    
    public static Connection getConnection() {
        
        Connection conn = null;    // Connection 객체를 생성
        try {
            // 연결할 url, 데이터베이스 ID, 데이터베이스 PW
            conn = DriverManager.getConnection(url, id, pw); // 실행하는 환경에 따라 입력
            System.out.println("Connection Success");            
        } catch (SQLException e) {            
            System.out.println("db을 연결하지 못했습니다");
            e.printStackTrace();
        }    
        return conn;
    }
    
    
}
 
cs

2. db.sql 파일

 - id, name, age, joindate라는 컬럼 4가지로 테이블을 만들어 두었다.

 - 테이블명은 user이다.

 

3. User.java 파일

client의 정보를 나타내는 객체를 생성하여 사용하고자 만들었다.

 

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package dto;
 
import java.io.Serializable;
 
public class User implements Serializable{
 
    private String id;
    private String name;
    private int age;
    private String joindate;
    
    public User() {}
 
    public User(String id, String name, int age, String joindate) {
        super();
        this.id = id;
        this.name = name;
        this.age = age;
        this.joindate = joindate;
    }
 
    
    public String getId() {
        return id;
    }
 
    public void setId(String id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public int getAge() {
        return age;
    }
 
    public void setAge(int age) {
        this.age = age;
    }
 
    public String getJoindate() {
        return joindate;
    }
 
    public void setJoindate(String joindate) {
        this.joindate = joindate;
    }
    
    @Override
    public String toString() {
        return "UserDto [id=" + id + ", name=" + name + ", age=" + age + ", joindate=" + joindate + "]";
    }
 
    
    
}
 
cs

4. DBClose.java

 실행 중인 객체들을 종료하도록 한다. 주의할 것은 실행된 순서와 반대로 close해줘야 한다는 것이다.

 

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
31
package db;
 
import java.sql.*;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
 
 
public class DBClose {
 
    public static void close(Connection conn, Statement psmt, ResultSet rs) {
        //사용순서와 반대로 close 함
        try {
            if(rs != null) {
                rs.close();
            }
            if(psmt != null) {
                psmt.close();
            }
            if(conn != null) {    
                conn.close();
            }
        } catch (SQLException e) {                
            e.printStackTrace();
        }            
    }
    
    
    
}
 
cs

 

5. JdbcTest.java

Insert, select, update, delete문을 작성한다.

 

< Insert >

 

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
31
32
33
34
35
36
37
38
39
40
// insert
    public boolean insert(String id, String name, int age) {
        
        // 쿼리문 작성(sql 문장)
        String sql = " insert into user(id, name, age, joindate) "
                + "    values(?, ?, ?, now())  ";
        
        Connection conn = null// 데이터베이스와 연결을 위한 객체
        PreparedStatement psmt = null// sql문을 데이터베이스에 보내기 위한 객체
        
        int count = 0;
        
        try {
            conn = DBConnection.getConnection();
            
            psmt = conn.prepareStatement(sql); // sql문 저장
            // DB는 인덱스가 1부터 시작. 위 ? 매개변수에 값을 지정
            // pstmt.set<데이터타입>(? 순서(1부터시작), 값)
            psmt.setString(1, id);
            psmt.setString(2, name);
            psmt.setInt(3, age);
            
            // executeUpdate(): 반환 값은 해당 sql문 실행에 영향을 받는 행 수(레코드 건 수)
            // 그렇게 영향을 받은 행 수를 변수 count에 저장하는 것이다.
            count = psmt.executeUpdate(); 
            
            // psmt.excuteQuery() : select
            // psmt.excuteUpdate() : insert, update, delete ..
            
            System.out.println("성공적으로 추가되었습니다");
            
        } catch (SQLException e) {
            System.out.println("추가되지 않았습니다");
            e.printStackTrace();
        } finally {
            DBClose.close(conn, psmt, null);
        }
        
        return count > 0 ? true : false;
    }
cs

 

< select >

 

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
// select
    // 1개의 데이터 취득(예를 들면, 1개의 object 취득)
    public User search(String id) {
        
        String sql = " select id, name, age, joindate"
                + "    from user "
                + "    where id = ? ";
        
        Connection conn = null// 데이터 베이스와 연결을 위한 객체
        PreparedStatement psmt = null// SQL 문을 데이터베이스에 보내기위한 객체
        ResultSet rs = null// SQL 질의에 의해 생성된 테이블을 저장하는 객체
        
        User user = null;
        
        try {
            conn = DBConnection.getConnection();
            
            psmt = conn.prepareStatement(sql);
            
            psmt.setString(1, id); // where id = ?의 ?에 들어갈 id
            
            
            // executeQuery(): ResultSet 객체의 값을 반환
            // executeQuery 메소드는 데이터 베이스에서 가져온 데이터를 resultSet에 담아 그 resultSet을리턴한다.
            rs = psmt.executeQuery();
            
            // rs.next() 를 이용해서 커서를 이동
            if(rs.next()) {
                String _id = rs.getString("id"); // 1이라고 적어도 된다. (select문에서 id, name, age, joindate 순서대로 나왔으므로 1,2,3,4)
                String _name = rs.getString("name");
                int _age = rs.getInt("age");
                String _joindate = rs.getString("joindate");
                
                user = new User(_id, _name, _age, _joindate);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBClose.close(conn, psmt, rs);
        }
        
        return user;
        
    }
    
    // 다수의 데이터 취득 
    public List<User> select() {
        
        String sql = " select id, name, age, joindate "
                + "    from user ";
        
        Connection conn = null;
        PreparedStatement psmt = null;
        ResultSet rs = null;
        
        List<User> list = new ArrayList<User>();
        
        try {
            conn = DBConnection.getConnection();
            psmt = conn.prepareStatement(sql);
            rs = psmt.executeQuery();
        
            while(rs.next()) {
                String _id = rs.getString("id");
                String _name = rs.getString("name");
                int _age = rs.getInt("age");
                String _joindate = rs.getString("joindate");
                
                User user = new User(_id, _name, _age, _joindate);
                list.add(user);
            }
            
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBClose.close(conn, psmt, rs);
        }
        
        return list;
        
    }
cs

 

< update >

 

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
31
32
33
// update
    
    public boolean update(String id, String name, int age) {
        
        String sql = " update user "
                + "    set name=?, age=? "
                + "    where id=? ";
        
        Connection conn = null;
        PreparedStatement psmt = null;
        
        int count = 0;
        
        try {
            conn = DBConnection.getConnection();
            psmt = conn.prepareStatement(sql);
            
            psmt.setString(1, name);
            psmt.setInt(2, age);
            psmt.setString(3, id);
            
            count = psmt.executeUpdate();
            
        } catch (SQLException e) {
            
            e.printStackTrace();
        } finally {
            DBClose.close(conn, psmt, null);
        }
        
        return count > 0 ? true : false// return count>0;
        
    }
cs

 

< delete >

 

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
// delete
    public boolean delete(String id) {
        
        String sql = " delete from user where id=?";
                
        Connection conn = null;
        PreparedStatement psmt = null;
        
        int count = 0;
        
        try {
            conn = DBConnection.getConnection();
            psmt = conn.prepareStatement(sql);
            
            psmt.setString(1, id);    
            count = psmt.executeUpdate();
            
        } catch (SQLException e) {
            
            e.printStackTrace();
        } finally {
            DBClose.close(conn, psmt, null);
        }
        
        return count > 0 ? true : false// return count>0;
        
    }
cs

 

이 메서드들을 호출하여 DB에 값을 입력, 검색, 수정, 삭제 등의 작업을 수행할 수 있다.

 

 

 

 

 

 

 

 

 

 

연관된 표들을 그룹화 한 것을 데이터베이스라고 표현할 수도 있지만, 이를 Schema라고 표현할 수 있다.

MySQL을 설치한 것은 곧 데이터베이스 서버를 설치한 것이다.

간단한 용어들

Theme. 테이블 만들기

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
show databases;
drop database opentutorials;
create database opentutorials;
use opentutorials;
 
CREATE TABLE topic (
id INT(11NOT NULL AUTO_INCREMENT,  
title VARCHAR(100NOT NULL-- 
description TEXT NULL,
created DATETIME NOT NULL,
author VARCHAR(30NULL,
profile VARCHAR(100NULL,
PRIMARY KEY(id)
);
/*
"topic"이라는 이름의 table을 만들었다. 위 코드에 대한 설명을 하자면, 
Not Null: 값이 없는 것을 허용하지 않겠다.
auto_increment: 기본적으로 시작값은 1이며, 각 새 레코드가 추가 될때마다 1씩 자동증가 한다.
int(11)에서, int는 Integer이고 11은 table에서 몇 개까지 노출시킬 지를 정한 것(11개만 저장할 수 있다는 것이 아니다)
varchar(100)에서 varchar는 문자열의 데이터 타입을 의미하고, 100은 100"글자"를 말한다.
text: varchar보다 긴 문자열의 데이터 타입
datetime: 날짜와 시간을 모두 표현할 수 있는 데이터 타입
primary key(column명): 괄호 안에 있는 column명이 가장 중요한 컬럼. 예컨대 이를 기준으로 다른 값들과 중복되지 않게 구분할 수 있다.
*/
 
cs

DESC topic;

위 코드에서 나온 용어들에 대해 정리해보면,

NULL, NOT NULL

NULL: 값이 없다

NOT NULL: NULL 값을 가지지 못하도록 지정한다.

 

cf) SQL의 주요 datatypes

1) 정수

 INT

2) 수치

 DECIMAL: 전체 자릿수, 소수 자릿수가 고정된 숫자 데이터 형식. 예를들어, DECIMAL(5,2)의 형식인 경우 234.5678은 234.58이 된다. (전체 자릿수 5개, 소수 둘째짜리까지 반올림)

3) 실수

 FLOAT

4) 날짜 및 시간

 DATE: 날짜

 TIME: 시간

 DATETIME: 날짜와 시간

5) 문자열

 VARCHAR, TEXT(이때, TEXT가 VARCHAR보다 최대 문자열 길이가 더 길다)

 

Theme. CRUD

Create: 생성한다

Read: 읽는다

Update: 수정한다.

Delete: 삭제한다

어떤 데이터베이스든 반드시 가지고 있는 4가지의 작업.

각각의 작업이 SQL에서 어떻게 이루어지고 있는지 하나씩 살펴보도록 하자.

 

1. Create

INSERT문을 이용한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
desc topic; -- desc: 테이블의 어떤 column이 있는지와 구조는 어떤지 나타냄
 
-- Create
INSERT INTO    topic (title, description, created, author, profile)
VALUES('MySQL''MySQL is..', now(), 'egoing''developer');
-- INSERT문을 통해 데이터를 생성(Create)할 수 있다.
-- id는 자동으로 증가하니까 생성해줄 필요가 없다.
 
INSERT INTO    topic (title, description, created, author, profile)
VALUES('Oracle''Oracle is..', now(), 'egoing''developer');
INSERT INTO    topic (title, description, created, author, profile)
VALUES('SQL Server''SQL Server is..', now(), 'duru''data administrator');
INSERT INTO    topic (title, description, created, author, profile)
VALUES('PostgreSQL''PostgreSQL is..', now(), 'taeho''data scientist, developer');
INSERT INTO    topic (title, description, created, author, profile)
VALUES('MongoDB''MongoDB is..', now(), 'egoing''developer');
SELECT * FROM topic; -- 모든 행 조회
cs

 

Create

2. Read

SELECT문을 이용한다.

1
2
3
-- 선택한 column에 대한 모든 행을 조회
SELECT id, title, created, author 
FROM topic;
cs

1
2
3
-- 선택한 column에 대한 모든 행을 조회 + 일정한 값을 가진 행만을 조회
SELECT id, title, created, author 
FROM topic WHERE author = 'egoing';
cs

1
2
3
-- 선택한 column에 대한 모든 행을 조회 + 일정한 값을 가진 행만을 조회 + 정렬(내림차순)
SELECT id, title, created, author 
FROM topic WHERE author = 'egoing' ORDER BY id DESC;
cs

1
2
3
-- 선택한 column에 대한 모든 행을 조회 + 일정한 값을 가진 행만을 조회 + 정렬(내림차순) + 출력되는 행의 개수(2개) 설정
SELECT id, title, created, author 
FROM topic WHERE author = 'egoing' ORDER BY id DESC LIMIT 2;
cs

3. Update

위 결과에서 id  = 2일 때의 title의 Oracle은 'ORACLE'로, description의 Oracle is는 'ORACLE is'로 수정해보자.

이때, WHERE와 같은 제어문을 반드시 주의해서 써줘야한다. 자칫 원하는 행뿐만 아니라 앞의 조건들을 만족한 행들의 값들이 한번에 수정되어 버리는 참사가 벌어질 수 있기 때문이다.

1
2
-- id가 2인 행의 title, description 값을 수정해주는 방법
UPDATE topic SET title = 'ORACLE', description = 'ORACLE is..' WHERE id = 2;
cs

그 결과 다시 SELECT * FROM topic;을 하면,

id = 2인 행의 값들이 수정된 것을 확인할 수 있다.

 

4. DELETE

위의 전체 행에 대한 결과에서 MongoDB에 대한 행을 지워보자.

1
2
3
-- MongoDB를 삭제해보자.
DELETE FROM topic WHERE id = 5;
SELECT * FROM topic;
cs

 

Theme. 관계형 데이터베이스의 이해(Relational Database)와 JOIN을 위한 테이블 나누기

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
-- Relational Database(관계형 데이터베이스)의 이해
-- 먼저, topic 테이블을 쪼개보자.
RENAME TABLE topic TO topic_backup;
SELECT * FROM topic_backup;
DESC topic_backup;
--
-- Table structure for table `author`
--
 
CREATE TABLE `author` (
  `id` int(11NOT NULL AUTO_INCREMENT,
  `name` varchar(20NOT NULL,
  `profile` varchar(200DEFAULT NULL,
  PRIMARY KEY (`id`)
);
 
--
-- Dumping data for table `author`
--
 
INSERT INTO `author` VALUES (1,'egoing','developer');
INSERT INTO `author` VALUES (2,'duru','database administrator');
INSERT INTO `author` VALUES (3,'taeho','data scientist, developer');
SELECT * FROM author;
DESC author;
--
-- Table structure for table `topic`
--
 
CREATE TABLE `topic` (
  `id` int(11NOT NULL AUTO_INCREMENT,
  `title` varchar(30NOT NULL,
  `description` text,
  `created` datetime NOT NULL,
  `author_id` int(11DEFAULT NULL,
  PRIMARY KEY (`id`)
);
 
--
-- Dumping data for table `topic`
--
 
INSERT INTO `topic` VALUES (1,'MySQL','MySQL is...','2018-01-01 12:10:11',1);
INSERT INTO `topic` VALUES (2,'Oracle','Oracle is ...','2018-01-03 13:01:10',1);
INSERT INTO `topic` VALUES (3,'SQL Server','SQL Server is ...','2018-01-20 11:01:10',2);
INSERT INTO `topic` VALUES (4,'PostgreSQL','PostgreSQL is ...','2018-01-23 01:03:03',3);
INSERT INTO `topic` VALUES (5,'MongoDB','MongoDB is ...','2018-01-30 12:31:03',1);
SELECT * FROM topic;
DESC topic;
cs

그 결과, 3가지 테이블에 대한 정보는 다음과 같다.

1. topic_backup(기존의 topic)

DESC topic_backup;

 

SELECT * FROM topic_backup;
 
2. author
 

DECS author;

 

SELECT * FROM author;

3. topic(새로운 topic)

DESC topic;

SELECT * FROM topic;
 

Theme. 관계형 데이터베이스의 이해(Relational Database)와 JOIN

JOIN을 통해 독립적인 테이블들을 읽을 때, 마치 하나인 것처럼 읽을 수 있게 된다.

위 topic과 author 테이블을 JOIN 해보자.

두 테이블이 결합될 수 있는 지점은 topic 테이블에서는 author_id, author 테이블에서는 id이다.

그래서 두 개의 테이블을 그 지점을 이용해서 합성해보면,

1
2
3
-- JOIN
SELECT * FROM topic LEFT JOIN author ON topic.author_id = author.id;
-- topic 테이블과 author 테이블을 author_id, id의 지점에서 JOIN한다.
cs

 

JOIN 결과

이를 중간의 author_id와 id column은 제외하고 보기 좋게 바꾸면,

(이때, id라는 column명이 겹치는데, 맨 앞의 id를 topic.id라고 명시해줘야 한다.)

즉, SELECT topic.id, title, description, created, name, profile FROM topic LEFT JOIN author ON topic.author_id = author.id;

라고 적는다. 그 결과,

이렇게 JOIN을 해놓으면 각각의 테이블을 독립적으로 관리하면서 수정하더라도, 다른 테이블을 다시 각각 고쳐줄 필요가 없는 장점이 있다. 

즉, 테이블 A,B,C가 있을 때, A와 B, A와 C를 각각 JOIN해줬다면,

A의 데이터를 수정하게 되었을 때, B와 C도 별도의 수정없이 자동으로 동시에 수정되게 된다.

 

 

'DB > MySQL' 카테고리의 다른 글

MySQL - JOIN(2)  (0) 2023.01.05
MySQL - JOIN(1)  (0) 2023.01.05
MySQL - 문법정리(2) - where, order, group, having...  (0) 2023.01.03
MySQL 문법(1) - select * from, insert into values 등등  (0) 2023.01.02

+ Recent posts