연관된 표들을 그룹화 한 것을 데이터베이스라고 표현할 수도 있지만, 이를 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

CRUD 기능이 포함된 주소록을 List를 이용하여 만들어보자.

먼저, 간단한 용어 정리를 하자면,

 

CRUD: 기본적인 데이터 처리 기능인 Create(생성, 추가), Read((읽기, 검색), Update(갱신, 수정) Delete(삭제)를 말한다.

DAO: DAO(Data Access Object) 는 데이터베이스의 data에 접근하기 위한 객체이다. DataBase에 접근 하기 위한 로직 & 비지니스 로직을 분리하기 위해 사용한다.

DTO: DTO(Data Transfer Object) 는 계층 간 데이터 교환을 하기 위해 사용하는 객체로, DTO는 로직을 가지지 않는 순수한 데이터 객체(getter & setter 만 가진 클래스)이다.

 

본 프로그램은 4개의 클래스를 통해 구성하였다.

1. MainClass

2. AddressDao

3. HumanDto

4. FileProc

 

전체적인 프로그램 실행 과정은 마지막에 설명하도록 하고,

먼저 각각의 클래스에 대한 설명과 코드를 나타내보자.

 

Theme. 각 클래스에 대한 설명 및 작성된 코드

 

1. MainClass

주소록의 menu 역할을 하는 클래스로 AddressDAO 클래스의 인스턴스를 통해 메서드를 호출하여 사용자가 원하는 메뉴를 선택하면 그에 따른 실행, 결과 출력 등을 하도록 한다.

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
package main;
 
import java.util.Scanner;
 
import dao.AddressDao;
 
public class MainClass {
 
    public static void main(String[] args)  {
        
        Scanner sc = new Scanner(System.in);
        
        AddressDao dao = new AddressDao();
        
        boolean end = false;
        
        // menu
        out:while(true) {
            
            System.out.println(" << 주소록 >> ");
            System.out.println("1. 지인추가");
            System.out.println("2. 지인삭제");
            System.out.println("3. 지인검색");
            System.out.println("4. 지인수정");
            System.out.println("5. 모두출력");
            System.out.println("6. 데이터저장");
            System.out.println("7. 종료");
            
            System.out.print(">> ");
            int choice = sc.nextInt();
            
            switch(choice) {
                case 1:
                    dao.insert();
                    break;
                case 2:
                    dao.delete();
                    break;
                case 3:
                    dao.select();
                    break;
                case 4:
                    dao.update();
                    break;
                case 5:
                    dao.allDataPrint();
                    break;
                case 6:    
                    dao.filesave();
                    break;
                case 7:        
                    end = true;                    
                    //System.exit(0);        // 강제종료
                    break out;
                default:
                    
            }
                    
            /*
            if(end) {
                System.out.println("프로그램을 종료합니다");
                break;
            }
            */
                        
        }
 
    }
 
}
 
 
 
 
 
cs

 

2. AddressDAO

CRUD 기능을 나타낼 메서드를 정의하는 것을 중심으로 FileProc 클래스와의 데이터 저장, 불러오기 기능을 나타낸다.

HumanDto 클래스로부터 각 사람에 대한 데이터를 가져와 실행한다.

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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
package dao;
 
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
 
import data.FileProc;
import dto.HumanDto;
 
public class AddressDao {
    
    Scanner sc = new Scanner(System.in);
 
    private List<HumanDto> list = new ArrayList<HumanDto>();
    
    private int count;
    
    private FileProc fileProc = null;  // composition(합성)
    
    public AddressDao() {
    
        fileProc = new FileProc("address");
        
        fileload();
    
    }
        
    public void insert() {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        
        System.out.println("지인을 추가합니다");
        
        System.out.print("이름 = ");
        String name = sc.next();
        
        System.out.print("나이 = ");
        int age = sc.nextInt();
        
        System.out.print("전화번호 = ");
        String phone = sc.next();
        
        System.out.print("주소 = ");
        String address = "";
        try {
            address = br.readLine(); 
        } catch (IOException e) {            
            e.printStackTrace();
        }
        
        System.out.print("메모 = ");
        String memo = sc.next();
            
        HumanDto dto = new HumanDto(name, age, phone, address, memo);
        list.add(dto);
    }
    
    public void delete() {
                
        System.out.print("삭제할 지인의 이름 = ");
        String name = sc.next();
        
        // 검색
        int index = search(name);
        
        if(index == -1) {
            System.out.println("지인의 정보를 찾을 수 없습니다");
        }
        else {            
            // 삭제
        
            list.remove(index);
            
            System.out.println("지정한 지인을 삭제하였습니다");
        }
    }
    
    public void select() { // 동명이인을 찾는다
        // 검색
        System.out.print("검색할 지인의 이름 = ");
        String name = sc.next();
    
        
        for (HumanDto h : list) {
            if(name.equals(h.getName())) {
                System.out.println(h.toString());
            }
        }        
    }
    
    public void update() {
        System.out.print("수정할 지인의 이름 = ");
        String name = sc.next();
        // 검색
        int index = search(name);        
        if(index == -1) {
            System.out.println("지인의 정보를 찾을 수 없습니다");
            return;
        }
        
        // 수정
        // phone
        // address
        System.out.println("데이터를 찾았습니다");
        System.out.print("전화번호 = ");
        String phone = sc.next();
        
        System.out.print("주소 = ");
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String address = "";
        try {
            address = br.readLine(); 
        } catch (IOException e) {            
            e.printStackTrace();
        }
        
        list.get(index).setPhone(phone);
        list.get(index).setAddress(address);
        
        System.out.println("정상적으로 수정되었습니다");
    }
    
    
    public int search(String name) {
        int index = -1;
        for (int i = 0; i < list.size(); i++) {
            HumanDto h = list.get(i);
            if(name.equals(h.getName())) {
                index = i;
                break;
            }
        }
        return index;
    }
        
    public void allDataPrint() {
        
        for (HumanDto humanDto : list) {
            System.out.println(humanDto.toString());
        }
        
    }    
    
    
    public void filesave() {
        String dataArr[] = new String[list.size()];
        for (int i = 0; i < list.size(); i++) {
            dataArr[i] = list.get(i).toString();
        }        
        
        fileProc.write(dataArr);
        
    }
    
    public void fileload() {
        
        String datas[] = fileProc.read();
    
        for (int i = 0; i < datas.length; i++) {
        
            String split[] = datas[i].split(":");
            
            HumanDto h = new HumanDto(    split[0], 
                                        Integer.parseInt(split[1]), 
                                        split[2],         
                                        split[3], 
                                        split[4] );            
            list.add(h);
        }
    }
}
 
 
 
 
 
 
 
 
 
 
 
 
 
cs

3. HumanDto

주소록에서 한 사람에 대한 데이터를 담는 클래스로 이름, 나이, 전화번호, 주소, 메모 등에 대한 항목이 존재한다.

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
package dto;
 
public class HumanDto {
 
    // 이름, 나이, 전화번호, 주소, 메모
    private String name;
    private int age;
    private String phone;
    private String address;
    private String memo;
    
    public HumanDto() {
    }
 
    public HumanDto(String name, int age, String phone, String address, String memo) {
        this.name = name;
        this.age = age;
        this.phone = phone;
        this.address = address;
        this.memo = memo;
    }
 
    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 getPhone() {
        return phone;
    }
 
    public void setPhone(String phone) {
        this.phone = phone;
    }
 
    public String getAddress() {
        return address;
    }
 
    public void setAddress(String address) {
        this.address = address;
    }
 
    public String getMemo() {
        return memo;
    }
 
    public void setMemo(String memo) {
        this.memo = memo;
    }
 
    @Override
    public String toString() {
        return name + ":" + age + ":" + phone + ":" + address + ":" + memo;
    }
    
}
 
 
 
 
 
 
cs

4. FileProc

컴퓨터 C드라이브에 파일을 생성하고, 이에 데이터를 저장하고 읽어오는 기능을 AddressDao 클래스와 함께 수행한다.

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
82
83
84
85
86
87
88
89
package data;
 
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Stack;
 
public class FileProc {
 
    // 파일 쓰기, 읽기
    private File file = null;
    
    public FileProc(String filename) {
        file = new File("c:\\tmp\\" + filename + ".txt");
        
        // 실제 파일이 생성되는 부분
        try {
            if(file.createNewFile()) {
                System.out.println("파일 생성 성공!");
            }else {
                System.out.println("기존의 파일이 있습니다");
            }
        } catch (IOException e) {            
            e.printStackTrace();
        }
    }
    
    public String[] read() {    
        
        String datas[] = null;
        try {
            BufferedReader br = new BufferedReader(new FileReader(file));
            
            // 데이터의 총 개수를 구한다
            int count = 0;
            String str = "";
            while((str = br.readLine()) != null) {
                count++;
            }
            br.close();
            
            // 배열 할당
            datas = new String[count];            
            
            // 파일로부터 배열에 저장
            br = new BufferedReader(new FileReader(file));
            
            int w = 0;
            while((str = br.readLine()) != null) {
                datas[w] = str;
                w++;
            }
            br.close();
            
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {            
            e.printStackTrace();
        }
        
        return datas;
    }
    
    public void write(String datas[]) {
        
        try {
            PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(file)));
            
            for (int i = 0; i < datas.length; i++) {
                pw.println(datas[i]);
            }
            
            pw.close();
            
        } catch (IOException e) {            
            e.printStackTrace();
        }    
        
        System.out.println("파일에 저장되었습니다");
    }
    
    
}
 
cs

 

 

Theme. 작성된 프로그램의 실행

1. 지인추가(Create)

주소록에 4명이 지인을 추가해보도록 한다.

처음 프로그램을 실행하면 나타나는 콘솔모습

지인 추가한 결과를 보면,

이를 파일에 저장하고, 저장이 올바르게 되었는지 확인해보자.

파일에도 올바르게 저장된 모습

 

2. 지인 검색(Read)

3. 지인 수정(Update)

진도준의 주소가 수정되었다.

 

4. 지인 삭제(Delete)

 

진양철이 삭제되었다.

 

5. 데이터를 저장하고 txt 파일을 확인해보자.

수정된 내용이 잘 저장되었다.

+ Recent posts