JSONObject로 생성, JSONObject 리스트 JSONArray에 넣기, JSONArray를 ArrayList에 넣기



1. string 형태의 배열문자열을 split 하여 string array에 넣는다. 


1
2
String[] myCodeArr = [01020304]
String[] motherCodeArr = [999897]
cs



2. string array에 들어간 데이터 값과 name, updateTime값을 JSONObject에 다시 넣는다.


1
2
3
4
5
6
JSONObject jsonObj1 = new JSONObject();

jsonObj1.put("myCode", myCodeArr);
jsonObj1.put("name", name);
jsonObj1.put("motherCode", motherCodeArr);
jsonObj1.put("updatedTime", updatedTime);
cs


1
2
3
4
5
6
  "myCode":["01","02","03","04"],
  "name":"jihyun",
  "motherCode":["99","98","97"],
  "updatedTime":"2019-11-05 12:48:12"
}
cs



3. JSONObject를 여러개 갖고 싶어 JSONArray 안에 다시 넣는다.


1
2
JSONArray jsonArr1 = new JSONArray();
jsonArr1.put(jsonObj1);
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
   { 
      "myCode":["01","02","03","04"],
      "name":"jihyun",
      "motherCode":["99","98","97"],
      "updatedTime":"2019-11-05 12:48:12"
   },
   { 
      "myCode":["11","22","33"],
      "name":"yumi",
      "motherCode":["20","30"],
      "updatedTime":"2019-11-05 12:48:12"
   }
]
cs



4. JSONArray에 담긴 것을 JSONObject 형식을 유지한 ArrayList로 만들고 싶다.

JSONArray에 담긴 것을 하나씩 JSONObject로 뽑아내어 ArrayList에 add 시킨다.

JSONObject[] jsons안에 array사이즈를 할당하고 toArray() 를 사용해 arrayJson이 갖고 있는 값의 형태로 arraylist를 생성한다.


1
2
3
4
5
6
7
8
9
ArrayList<JSONObject> arrayJson = new ArrayList<JSONObject>();
 
for (int k = 0; k < jsonArr1.length(); k++) {
    JSONObject tempJson = jsonArr1.getJSONObject(k);
    arrayJson.add(tempJson);
}
 
JSONObject[] jsons = new JSONObject[arrayJson.size()];
arrayJson.toArray(jsons);
cs



5. 전체 소스


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
private void arrIntoJson() throws JSONException {
 
    String name = "";
    String myCode = "";
    String motherCode = "";
    JSONArray jsonArr1 = new JSONArray();
    
    for(int i=0; i<2; i++) {
    
        if(i==0) {
            name = "jihyun";
            myCode = "[01,02,03,04]";
            motherCode = "[99,98,97]";
        }else {
            name = "yumi";
            myCode = "[11,22,33]";
            motherCode = "[20,30]";
        }
        
        String updatedTime = String.valueOf(DateUtil.getLocalDateTime("yyyy-MM-dd HH:mm:ss"));
        String[] myCodeArr = myCode.substring(1, myCode.length()-1).split(",");
        String[] motherCodeArr = motherCode.substring(1, motherCode.length()-1).split(",");
        
        JSONObject jsonObj1 = new JSONObject();
        jsonObj1.put("name", name);
        jsonObj1.put("myCode", myCodeArr);
        jsonObj1.put("motherCode", motherCodeArr);
        jsonObj1.put("updatedTime", updatedTime);
        jsonArr1.put(jsonObj1);
    }
    
    ArrayList<JSONObject> arrayJson = new ArrayList<JSONObject>();
    
    for (int k = 0; k < jsonArr1.length(); k++) {
        JSONObject tempJson = jsonArr1.getJSONObject(k);
        arrayJson.add(tempJson);
    }
    
    JSONObject[] jsons = new JSONObject[arrayJson.size()];
    arrayJson.toArray(jsons);
    
    System.out.println(jsons);
}
cs


arrayJson의 값


1
2
3
4
5
6
7
8
9
10
11
12
13
14
   { 
      "myCode":["01","02","03","04"],
      "name":"jihyun",
      "motherCode":["99","98","97"],
      "updatedTime":"2019-11-05 12:48:12"
   },
   { 
      "myCode":["11","22","33"],
      "name":"yumi",
      "motherCode":["20","30"],
      "updatedTime":"2019-11-05 12:48:12"
   }
]
cs



사실 IaaS, PaaS, SaaS 를 소프트웨어 공학 시간에 배운적이 있지만

실제로 사용해보기 전까진 잘 알지 못했다. 


개념은 이해 되는데 실제 개발 및 테스트를 위해 사용해보고 

개념을 다시 살펴봤는데 본인이 사용한 서비스가 어떤 서비스였는지 잘 확인 할 수 있었다.





1. IaaS


서비스로서의 인프라스트럭처(Infrastructure as a Service, IaaS)는 서버, 스토리지, 네트워크를 필요에 따라 인프라 자원을 사용할 수 있게 클라우드 서비스를 제공하는 형태이다. 


간략하게 IaaS는 컴퓨터만 할당 받는것이다.


너가 만약 웹개발을 하여 만든 소스를 올리고 싶다면 


OS : 리눅스(16.x,18.x) 윈도우(7,10) 선택

Web Server : 톰캣(8.x,9.x), 웹로직, etc 선택

DB : mysql, mssql, maria, etc 선택 


버전까지 선택하여 개발환경을 꾸릴수 있다.

선택권이 모두 개발자에게 넘어간 것이다. 컴퓨터 환경만 빌려서 사용한다.


대표적인 서비스로




AWS EC2, Google Cloud Platform, Azure Virtual Machines, Naver Cloud Platform 이 있다.


위 서비스들은 1년간 무료사용 서비스를 제공한다.


초보 개발자들이나 돈이 없는 개발자들은 각각 1년간 IaaS를 돌려쓰며 돈을 아껴보자.

본인도 개발 및 간단한 테스트를 위해 1년간 돌려가며 써볼 생각이다. 

현재 1년간 무료 AWS EC2 서비스를 사용중인데 매우 만족하며 쓰고 있다.



2. PaaS


PaaS (Platform as a Service)라고도하는 클라우드 플랫폼 서비스는 

주로 애플리케이션에 사용되는 동안 특정 소프트웨어에 클라우드 구성 요소를 제공한다. 

PaaS는 개발자가 맞춤형 애플리케이션을 개발하고 구축 할 수있는 프레임 워크를 제공한다. 

모든 서버, 스토리지 및 네트워킹은 엔터프라이즈 또는 타사 공급자가 관리 할 수 ​​있으며 개발자는 응용 프로그램 관리를 유지할 수 있다.


간략하게 PaaS는 플랫폼서비스로


개발자는 IaaS에서 했던 복잡한 설치 및 환경설정을 하지 않아도 된다.

PaaS에서 정해준 OS, 버전, 어플리케이션 등이 있으므로 개발자는 완성된 소스를 올리기만 하면 된다.


개발자의 선택권이 줄어들었지만 그만큼 플랫폼에게 권한을 위임함으로써 

복잡한 서버, 환경구성에 신경쓰지 않아도 된다.


당연히 IaaS보다 PaaS가 비용면에서 비싸다.




AWS Elastic Beanstalk, Windows Azure, Heroku 등이 있다.


본인은 NodeJS소스를 Heroku에 바로 올려보았는데 정말 소스만 올리면 바로 올라가는 것을 확인 할 수 있었다.



3. SaaS


서비스로서의 소프트웨어(Software as a Service, SaaS)는 소프트웨어 및 관련 데이터는 중앙에 호스팅되고 사용자는 웹 브라우저 등의 클라이언트를 통해 접속하는 형태의 소프트웨어 전달 모델이다. 주문형 소프트웨어(on-demand software, 온디맨드 소프트웨어)라고도 한다.


간략하게 서비스를 이용할 수 있는 소프트웨어를 말한다.




Google Apps, Mail, Youtube, Blog ... 등이 있다.


1. 자바스크립트 이용한 pc, 모바일 체크, DOMContentLoaded 이벤트 사용하기


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
<script type="text/javascript">
 
var onresize = function() {
    var width = document.body.clientWidth;
    var height = document.body.clientHeight;
    if(width <= 1575){
        smallMenu();
    }else{
        largeMenu();
    }
};
 
var top_frame01 = document.getElementById('top_frame01');
    
var smallMenu = function(){
    top_frame01.setAttribute( 'rows''120,*' )
};
 
var largeMenu = function(){
    top_frame01.setAttribute( 'rows''90,*' )
};
 
// 모바일, pc 체크
window.mobilecheck = function() {
      var check = false;
      (function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m||s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))) check = true;})(navigator.userAgent||navigator.vendor||window.opera);
      return check;
};
 
// DOMContentLoaded
window.addEventListener('DOMContentLoaded'function(){
    if(mobilecheck()){
        console.log('mobile');
        smallMenu();
    }else{
        console.log('pc');
        largeMenu();
    }
});
 
window.addEventListener("resize"onresize);
 
</script>
cs


index.jsp가 화면에 로딩될때 접근한 기기가 PC인지 모바일인지 확인 후 상단의 메뉴 사이즈를 줄여주려고 한다.


처음에 windows.onload = function(){} 을 사용했으나 모든 콘텐츠가 로드된 후 실행되어 스크립트가 늦게 실행되어 화면이 늦게 바뀌는 문제점이 있었다.


그래서 DOMContentLoaded 이벤트를 사용했다.  

DOMContentLoaded는 최초 HTML 문서가 완전히 로드 및 파싱되었을때 발생되고, 

스타일시트나 이미지 및 서브프레임 로드가 끝나기를 기다리지 않는다고 한다.


$(document).ready(function(){}); 은 jquery에서 쓰는 것인데 DOMContentLoaded 이벤트와 동일하다.



1. 프로젝트 구조 생성



- model 하위에 entity package를 생성하고 User 클래스를 만든다.

- repository package를 생성하고 하위에 UserRepository 인터페이스를 생성한다.

- test 패키지 하위에 repository package아래에 UserRepositoryTest라는 test클래스를 만든다.



2. user 테이블 생성


1
2
3
4
5
6
7
8
9
10
CREATE TABLE `test`.`user` (
  `id` BIGINT(20NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(45NULL,
  `email` VARCHAR(45NULL DEFAULT NULL,
  `phone_number` VARCHAR(45NULL DEFAULT NULL,
  `reg_dt` VARCHAR(45NOT NULL,
  `reg_user` VARCHAR(45NOT NULL,
  `mod_dt` VARCHAR(45NULL DEFAULT NULL,
  `mod_user` VARCHAR(45NULL DEFAULT NULL,
  PRIMARY KEY (`id`));
cs


MySQL Tool (workbench, heidiSQL) 을 통해 test 데이터베이스에 user테이블을 생성한다.

생성할때 컬럼은 snake_case를 사용하여 각 단어와 단어 사이에  _언더바로 표시한다.



3. User 모델 생성


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.example.test.model.entity;
 
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.time.LocalDateTime;
 
@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String email;
    private String phoneNumber;
    private LocalDateTime regDt;
    private String regUser;
    private LocalDateTime modDt;
    private String modUser;
}
cs



자바에선 user테이블의 컬럼명에 맞춰 

camel case를 사용하여 모델 User클래스를 만든다.



4. UserRepository 인터페이스 생성


1
2
3
4
5
6
7
8
9
10
package com.example.test.repository;
 
import com.example.test.model.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
 
@Repository
public interface UserRepository extends JpaRepository<User,Long> {
 
}
cs


JpaRepository를 상속받아 생성한다.



5. UserRepositoryTest 클래스 생성


5.1 create


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
package com.example.test.repository;
 
import com.example.test.TestApplicationTests;
import com.example.test.model.entity.User;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
 
import java.time.LocalDateTime;
 
public class UserRepositoryTest extends TestApplicationTests {
 
    @Autowired
    private UserRepository userRepository;
 
    @Test
    public void create(){
        User user = new User();
        user.setName("user1");
        user.setEmail("user1@gmail.com");
        user.setPhoneNumber("010-1111-2222");
        user.setRegDt(LocalDateTime.now());
        user.setRegUser("shlee0882");
 
        User newUser = userRepository.save(user);
        System.out.println(newUser);
    }
}
 
cs


User 모델을 객체로 가져와 값을 set하고 

DI (의존성주입)를 사용해 UserRepository로 만든 객체에 save한다.


Test를 실행하면 데이터가 잘 들어간것을 확인할 수 있다.




5.2 read


1
2
3
4
5
6
7
8
    @Test
    public void read(){
        Optional<User> user = userRepository.findById(1L);
 
        user.ifPresent(selectUser ->{
            System.out.println("user: "+selectUser);
        });
    }
cs


read 메소드를 run하면 

id는 모델에서 long으로 선언 되어 있으므로 L을 붙여 id가 1번인 데이터를 찾는다.

데이터를 찾아 user객체에 담아주고 출력한다.


출력결과


1
user: User(id=1, name=user1, email=user1@gmail.com, phoneNumber=010-1111-2222, regDt=2019-08-09T09:25:28.653, regUser=shlee0882, modDt=2019-08-09T09:27:51.381, modUser=shlee0882)
cs


5.3 update


1
2
3
4
5
6
7
8
9
10
11
12
13
    @Test
    public void update(){
        Optional<User> user = userRepository.findById(1L);
 
        user.ifPresent(selectUser ->{
            selectUser.setUserAccount("modUser1");
            selectUser.setEmail("modUser1@gmail.com");
            selectUser.setModDt(LocalDateTime.now());
            selectUser.setModUser("shlee0882");
            User newUser = userRepository.save(selectUser);
            System.out.println("user: "+newUser);
        });
    }
cs


update 메소드를 run하면

id가 1번인 데이터를 찾아 user객체에 담고

담은 user의 객체의 값을 새로 set해주고 save하면 

기존의 데이터가 있다면 update가 일어난다.


출력결과


1
user: User(id=1, name=modUser1, email=modUser1@gmail.com, phoneNumber=010-1111-2222, regDt=2019-08-09T09:25:28.653, regUser=shlee0882, modDt=2019-08-09T11:20:17.179, modUser=shlee0882)
cs


5.4 delete


1
2
3
4
5
6
7
8
9
10
11
12
13
    @Test
    public void delete(){
        Optional<User> user = userRepository.findById(1L);
 
        Assert.assertTrue(user.isPresent());    // true
        user.ifPresent(selectUser ->{
            userRepository.delete(selectUser);
        });
 
        Optional<User> deleteUser = userRepository.findById(1L);
 
        Assert.assertFalse(deleteUser.isPresent());    // false
    }
cs


delete메소드는 id를 찾아 있다면 true, 

데이터 삭제 후 id가 있는지 확인 후 없다면 false를 통과한다.



5.5 Transactional



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
    @Test
    @Transactional
    public void update(){
        Optional<User> user = userRepository.findById(1L);
 
        user.ifPresent(selectUser ->{
            selectUser.setName("modUser1");
            selectUser.setEmail("modUser1@gmail.com");
            selectUser.setModDt(LocalDateTime.now());
            selectUser.setModUser("shlee0882");
            User newUser = userRepository.save(selectUser);
            System.out.println("user: "+newUser);
        });
    }
 
    @Test
    @Transactional
    public void delete(){
        Optional<User> user = userRepository.findById(1L);
 
        Assert.assertTrue(user.isPresent());    // true
        user.ifPresent(selectUser ->{
            userRepository.delete(selectUser);
        });
 
        Optional<User> deleteUser = userRepository.findById(1L);
 
        Assert.assertFalse(deleteUser.isPresent());    // false
    }
cs


transactional 어노테이션을 넣으면

update와 delete 시 RollBack 되는것을 확인할 수 있다. 


1
Rolled back transaction for test: [DefaultTestContext@576dad90 testClass = UserRepositoryTest, testInstance = com.example.test.repository.UserRepositoryTest@97bd416, testMethod = delete@UserRepositoryTest, testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration@5baaa549 testClass = UserRepositoryTest, locations = '{}', classes = '{class com.example.test.TestApplication}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@7097fbf1, org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@7ed6156f, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@2c5d456b, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@6b04043b], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.populatedRequestContextHolder' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.resetRequestContextHolder' -> true]]
cs





평소 Notepad++를 많이 사용하는데 

여러개의 텍스트파일을 띄워두고 저장하지 않고

기록만 해두었다 필요한 내용을 정리하는 편이다.


Notepad++ 사용시 save 할지 말지 알림창이 뜨는경우가 있다. 




설정 > 기본설정 > 백업 > 세션 스냅샷 체크를 2개 해준다.





이제 여러 탭을 열어 텍스트를 작성하고

텍스트 저장없이 Notepad++를 껐다 켰다 할수 있다.



1. 유저 삭제하기


1
drop user [user명] cascade;
cs


[ORA-28014: cannot drop administrative users] 발생 시


1
alter session set "_oracle_script"=true;
cs



[ORA-01940: cannot drop a user that is currently connected] 발생 시


현재 session에 대해 select 하여 session을 KILL해줘야 한다.



- session 조회 하기

1
select sid,serial# from v$session where username = [user명 대문자로];
cs


- session KILL 하기

1
ALTER SYSTEM KILL SESSION '[SID], [SERIAL]';
cs


- use drop 하기

1
drop user dev_emart cascade;
cs



2. 유저 생성하기


1
2
3
4
5
6
7
8
9
alter session set "_ORACLE_SCRIPT"=true;
 
create user [user명] identified by [패스워드];
 
grant create session to [user명];
 
grant connect, resource to [user명];
 
alter user [user명] default tablespace users quota unlimited on users;
cs


그동안 단일 건이나 간단한 IF문만 사용하여

프로시저를 생성했는데 MySQL에서도 Oracle의 Cursor같이 여러개의 데이터를 뽑아와 

데이터를 반복하여 작업을 진행해보려한다.



1. TEST 테이블 생성하기


1
2
3
4
5
6
7
8
9
CREATE TABLE `TEST_TB1` (
    `id` BIGINT(20NOT NULL AUTO_INCREMENT,
    `name` VARCHAR(50NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci',
    `useYn` VARCHAR(50NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci',
    PRIMARY KEY (`id`)
)
COLLATE='utf8mb4_unicode_ci'
ENGINE=InnoDB
AUTO_INCREMENT=6;
cs



2. 기초 데이터 넣기


1
2
3
4
5
6
7
8
9
-- auto increment 초기화
ALTER TABLE TEST_TB1 AUTO_INCREMENT = 0;
 
-- 데이터 삽입
INSERT INTO TEST_TB1(name, useYn) VALUES('조현영''Y');
INSERT INTO TEST_TB1(name, useYn) VALUES('박초아''Y');
INSERT INTO TEST_TB1(name, useYn) VALUES('김태연''Y');
INSERT INTO TEST_TB1(name, useYn) VALUES('김지숙''Y');
INSERT INTO TEST_TB1(name, useYn) VALUES('이상현''Y');
cs


테이블 조회 결과 





3. 프로시저 만들기


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
DELIMITER $$
DROP PROCEDURE  IF EXISTS test_proc1;
 
CREATE PROCEDURE test_proc1()
 
BEGIN
  DECLARE done INT DEFAULT FALSE;
  DECLARE v_count INT DEFAULT -1;
  DECLARE v_id varchar(20);
  DECLARE v_name varchar(20);
  DECLARE v_useYn varchar(20);
    
  -- select한 결과를 cursor1로 정의 
  DECLARE cursor1 CURSOR FOR 
   SELECT id
         , name
         , useYn
     FROM TEST_TB1;
 
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
 
  OPEN cursor1;
 
  my_loop: LOOP
 
  -- loop 하며 cursor1의 데이터를 불러와 변수에 넣는다.
  FETCH cursor1 
   INTO v_id
        , v_name
        , v_useYn;
    
     SET v_count = v_count +1 ; 
 
    -- cursor1 반복이 끝나면 loop 빠져나간다.
    IF done THEN
      LEAVE my_loop;
    END IF;
     
     IF(v_id = 1) THEN
         UPDATE TEST_TB1
           SET name = '전효성'
         WHERE id = v_id;
 
    ELSEIF (v_id = 2) THEN
    INSERT INTO TEST_TB1(name, useYn)
         VALUES('insert값''N');
         
    ELSE 
         UPDATE TEST_TB1
           SET name = CONCAT(v_name, v_id)
         WHERE id = v_id;
         
     END IF;
     
  END LOOP;
 
  SELECT v_count; 
 
  -- 커서를 닫는다. 
  CLOSE cursor1;
 
END $$
 
DELIMITER ;
 
cs



cursor1에서 select한 데이터를 모두 갖고 있고

fetch를 통해 cursor의 데이터를 변수에 담고


변수에 담은 데이터를 하나씩 LOOP를 돌면서

IF문에 걸릴경우 UPDATE나 INSERT문을 만나

처리를 진행하게 된다.


LOOP를 돌릴때마다 변수의 count를 올리고 있다.



4. 프로시저 호출하기


1
CALL test_proc1();
cs



프로시저를 실행하게 되면 기존 데이터가 변경되고 신규 데이터가 추가된 것을 확인 할 수 있다.



테이블 백업을 수행하는 프로시저를 생성해보려고 한다.

기존 테이블(직원, 휴가, 휴가기록)에서 백업 테이블을 새로 생성하는 프로시저를 만든다.

프로시저를 생성하고 이벤트 스케쥴(event schedule)까지 걸어보겠다.



1. MySQL 프로시저 생성하기


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
DELIMITER $$
DROP PROCEDURE  IF EXISTS backup_proc;
 
CREATE PROCEDURE backup_proc()
 
BEGIN
    DROP TABLE IF EXISTS BACKUP_EMP;
    CREATE TABLE BACKUP_EMP SELECT * FROM EMP_EMPLOYEE;
    
    DROP TABLE IF EXISTS BACKUP_VAC;
    CREATE TABLE BACKUP_VAC SELECT * FROM VAC_VACATION;
    
    DROP TABLE IF EXISTS BACKUP_VAC_HIS;
    CREATE TABLE BACKUP_VAC_HIS SELECT * FROM VAC_HISTORY;
    
    SELECT '테이블 백업 성공';
END $$
 
DELIMITER ;
cs


백업테이블이 존재한다면 드랍하고 다시 생성할 것이고

없다면 백업테이블을 기존테이블에서 새로 생성한다는 간단한 쿼리이다.


프로시저를 저장했다면 프로시저를 호출해보자.



2. 프로시저 호출하기


1
CALL backup_proc();
cs





프로시저가 성공적으로 실행됐다면 select 구문에서 설정한 '테이블 백업 성공' 이라는 결과값이 나오고

BACKUP 테이블이 3개 생성된 것을 확인 할 수 있다.


3. 이벤트 스케쥴러 사용하기


매번 프로시저를 call해서 backup 테이블을 만들수는 없는 것이다.

이벤트 스케쥴러에 등록하여 DAY, MONTH, TIME 별로 시간을 지정해 준다면 자동으로 이벤트가 실행될 것이다.



- 이벤트 스케쥴러 ON


1
2
SHOW VARIABLES LIKE 'event%';
SET GLOBAL event_scheduler = ON ;
cs



- 이벤트 만들기


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
-- 매일 반복해서 실행
CREATE EVENT everyDayEvent1
    ON SCHEDULE 
 EVERY 1 DAY
STARTS '2019-07-30 00:00:00'
    DO CALL backup_proc();
 
-- 1달마다 반복해서 실행
CREATE EVENT everyMonthEvent1
    ON SCHEDULE 
 EVERY 1 MONTH
STARTS '2019-07-30 00:00:00'
    DO CALL backup_proc();
 
-- 1년마다 반복해서 실행
CREATE EVENT everyYearEvent1
    ON SCHEDULE 
 EVERY 1 YEAR
STARTS '2019-01-01 00:00:00'
    DO CALL backup_proc();
cs


이벤트를 만들고 스케쥴을 걸어 프로시저를 실행하는 구문이다.

이벤트를 생성하면 현재 등록된 이벤트의 목록을 확인해야 한다.



- 등록된 이벤트 조회하기


1
SELECT * FROM information_schema.`EVENTS` ;
cs


- 이벤트 삭제하기


1
2
3
DROP EVENT IF EXISTS everyDayEvent1;
DROP EVENT IF EXISTS everyMonthEvent1;
DROP EVENT IF EXISTS everyYearEvent1;
cs


백업 테이블명에 백업날짜를 붙여만들거나 

백업 테이블명을 각각 다르게하여 각각 스케쥴링을 걸어놓아 

백업을 정기적으로 할 수 있을 것 같다.



+ Recent posts