본문 바로가기
혼공학습단 12기

[혼공S] 6주차를 마무리 하며

by jaeheon0520 2024. 8. 17.

 

벌써 마지막 주차라니...! 

 

12기 활동은 다른 일정이랑 너무 겹치다 보니 완주에 의의를 두게 되었다는 게 너무 아쉽다.

 

하지만 덕분에 포기하지 않고 책 한 권을 다 볼 수 있었고, 방학 동안의 불안을 정리할 수 있었다.

 

담주는 목요일에 첫 세미나가 있고, 토요일에 SQLD 시험이 있다.

 

12기분들 중에도 SQLD 시험에 응시하는 분이 많던데 모두 좋은 결과가 있으면 좋겠다!

 

함께한 족장님과 12기분들 너무 감사하고 고생 많으셨습니다! 기회가 된다면 13기로 다시 만나요~

 

(각 단원별 학습 내용 정리는 '혼공학습단 12기' 카테고리 안에 있습니다!)

 

기본 숙제

p. 363 market_db의 고객 테이블(member)에 입력된 회원의 정보가 변경될 때 변경한 사용자, 시간, 변경 전의 데이터 등을 기록하는 트리거 작성하고 인증하기

 

우선 연습용으로 회원 테이블에서 간단히 아이디, 이름, 인원, 주소 4개의 열을 복사한 singer 테이블을 만들자.

 

USE market_db;
CREATE TABLE singer (SELECT mem_id, mem_name, mem_number, addr FROM member);

 

singer 테이블에 INSERT 나 UPDATE 작업이 일어나는 경우, 변경되기 전의 데이터를 저장할 백업 테이블을 만들자.

 

그리고 백업 테이블에 기본미션에서 요구하는 변경한 사용자(modUser), 변경된 시간(modDate)을 추가하자.

 

DROP TABLE IF EXISTS backup_singer;
CREATE TABLE backup_singer
( mem_id  	CHAR(8) NOT NULL , 
  mem_name    	VARCHAR(10) NOT NULL, 
  mem_number    INT NOT NULL, 
  addr	  	CHAR(2) NOT NULL,
  modType  	CHAR(2), -- 변경된 타입. '수정' 또는 '삭제'
  modDate  	DATE, -- 변경된 날짜
  modUser  	VARCHAR(30) -- 변경한 사용자
);

 

이제 변경(UPDATE)과 삭제(DELETE)가 발생할 때 작동하는 트리거를 singer 테이블에 부착해 보자.

 

먼저 변경(UPDATE)이 발생했을 때 작동하는 singer_updateTrg 트리거를 만들어보자.

 

DROP TRIGGER IF EXISTS singer_updateTrg;
DELIMITER $$
CREATE TRIGGER singer_updateTrg  -- 트리거 이름
    AFTER UPDATE -- 변경 후에 작동하도록 지정
    ON singer -- 트리거를 부착할 테이블
    FOR EACH ROW 
BEGIN
    INSERT INTO backup_singer VALUES( OLD.mem_id, OLD.mem_name, OLD.mem_number, 
        OLD.addr, '수정', CURDATE(), CURRENT_USER() );
END $$ 
DELIMITER ;

 

OLD 테이블은 UPDATE나 DELETE가 수행될 때, 변경되기 전의 데이터가 잠깐 저장되는 임시 테이블이다. MySQL에서 내부적으로 제공되는 테이블이라고 하는데 사용자 입장에서 굉장히 편리한 테이블인 것 같다.

 

이번에는 삭제(DELETE)가 발생했을 때 작동하는 singer_deleteTrg 트리거를 생성해 보자.

 

DROP TRIGGER IF EXISTS singer_deleteTrg;
DELIMITER $$
CREATE TRIGGER singer_deleteTrg  -- 트리거 이름
    AFTER DELETE -- 삭제 후에 작동하도록 지정
    ON singer -- 트리거를 부착할 테이블
    FOR EACH ROW 
BEGIN
    INSERT INTO backup_singer VALUES( OLD.mem_id, OLD.mem_name, OLD.mem_number, 
        OLD.addr, '삭제', CURDATE(), CURRENT_USER() );
END $$ 
DELIMITER ;

 

이제 변경과 삭제 시에 작동하는 트리거는 모두 생성되었다.

 

이제 데이터를 변경하고 backup_singer을 확인해 보자.

 

UPDATE singer SET addr = '영국' WHERE mem_id = 'BLK';
DELETE FROM singer WHERE mem_number >= 7;

SELECT * FROM backup_singer;

 

backup_singer 테이블을 조회해 본 결과 1건의 수정과 4건의 삭제에 대한 변경 전의 데이터,  변경한 사용자, 시간, 등의 데이터가 잘 기록되어 있는 것을 확인할 수 있다.

 

 

선택 숙제

p. 402 GUI 응용 프로그램 만들고 인증하기

 

사용자가 Tkinter를 통해 입력한 데이터를 MySQL 데이터베이스에 저장하거나, 데이터베이스에서 데이터를 조회하여 표시하는 간단한 GUI를 만들어보는 과제였다.

 

전체코드

import pymysql
from tkinter import *
from tkinter import messagebox

## 데이터베이스에 데이터 삽입
def insertData():
    con, cur = None, None
    data1, data2, data3, data4 = "", "", "", ""
    sql = ""

    conn = pymysql.connect(host='127.0.0.1', user='root',
                           password='1234', db='soloDB', charset='utf8')
    cur = conn.cursor()

    data1 = edt1.get(); data2 = edt2.get()
    data3 = edt3.get(); data4 = edt4.get()
    sql = "INSERT INTO userTable VALUES('" + data1 + "','" + \
          data2 + "','" + data3 + "','" + data4 + "')"
    cur.execute(sql)

    conn.commit()
    conn.close()

    messagebox.showinfo('성공', '데이터 입력 성공')

## 데이터베이스에서 데이터 조회
def selectData():
    strData1, strData2, strData3, strData4 = [], [], [], []

    conn = pymysql.connect(host='127.0.0.1', user='root',
                           password='1234', db='soloDB', charset='utf8')
    cur = conn.cursor()
    cur.execute("SELECT * FROM userTable")

    strData1.append("사용자 ID"); strData2.append("사용자 이름")
    strData3.append("사용자 이메일"); strData4.append("사용자 출생연도")
    strData1.append("-----------"); strData2.append("-----------")
    strData3.append("-----------"); strData4.append("-----------")

    while (True):
        row = cur.fetchone()
        if row == None:
            break
        strData1.append(row[0]); strData2.append(row[1])
        strData3.append(row[2]); strData4.append(row[3])

    listData1.delete(0, listData1.size() - 1)
    listData2.delete(0, listData2.size() - 1)
    listData3.delete(0, listData3.size() - 1)
    listData4.delete(0, listData4.size() - 1)

    for item1, item2, item3, item4 in zip(strData1, strData2, strData3, strData4):
        listData1.insert(END, item1)
        listData2.insert(END, item2)
        listData3.insert(END, item3)
        listData4.insert(END, item4)

    conn.close()

## 메인 GUI 코드
root = Tk()
root.geometry("600x300")
root.title("완전한 GUI 응용 프로그램")

edtFrame = Frame(root)
edtFrame.pack()
listFrame = Frame(root)
listFrame.pack(side=BOTTOM, fill=BOTH, expand=1)

edt1 = Entry(edtFrame, width=10); edt1.pack(side=LEFT, padx=10, pady=10)
edt2 = Entry(edtFrame, width=10); edt2.pack(side=LEFT, padx=10, pady=10)
edt3 = Entry(edtFrame, width=10); edt3.pack(side=LEFT, padx=10, pady=10)
edt4 = Entry(edtFrame, width=10); edt4.pack(side=LEFT, padx=10, pady=10)

btnInsert = Button(edtFrame, text="입력", command=insertData)
btnInsert.pack(side=LEFT, padx=10, pady=10)
btnSelect = Button(edtFrame, text="조회", command=selectData)
btnSelect.pack(side=LEFT, padx=10, pady=10)

listData1 = Listbox(listFrame, bg='yellow'); listData1.pack(side=LEFT, fill=BOTH, expand=1)
listData2 = Listbox(listFrame, bg='yellow'); listData2.pack(side=LEFT, fill=BOTH, expand=1)
listData3 = Listbox(listFrame, bg='yellow'); listData3.pack(side=LEFT, fill=BOTH, expand=1)
listData4 = Listbox(listFrame, bg='yellow'); listData4.pack(side=LEFT, fill=BOTH, expand=1)

root.mainloop()

 

1. 초기화면

 

2. 데이터 입력

 

3. 데이터 조회 (2 에서 입력한 test 데이터 확인)

 

12기도 너무 감사했습니다!!

 

오늘 하루도 쌓였다.