본문 바로가기

2. MySQL | MongoDB

3/31(금) IT K-DT(22일차) / 7.평가

 


문제

 

주어진 요구 사항을 확인한 후, 문제의 답안을 작성하세요
다음의 요구사항에 따라 제공된 필드를 참고하여 학생관리 프로그램의 시나리오를 자유롭게 만들고 

프로그램을 작성하세요.

(학생 테이블 필드 : 학번, 이름, 연락처, 이메일, 주소, 등록된 날짜)
(성적 테이블 필드 : 학번, 자바점수, 파이썬점수, C언어점수, 등록된 날짜, 총점, 평균)

1. 학생을 등록한다. (10점)
2. 학생의 등록된 정보를 성적(평균)을 기준으로 내림차순으로 출력한다. (10점)
(단, 학생의 점수가 있을 경우 점수도 같이 출력한다. 

등록된 학생의 전체 수와 해당 학생의 석차를 같이 출력한다. 동점인 경우 학번으로 내림차순으로 함)
3. 학생정보를 수정한다. (10점)
4. 학생정보를 삭제한다. 학생정보를 삭제할 경우 점수도 같이 삭제한다. (10점)
5. 학생정보를 검색한다. (10점)
(단, 학생의 점수가 있을 경우 점수도 같이 출력한다.)
6. 학생점수를 등록한다. 점수를 등록할 때 총점, 평균을 계산하여 같이 저장한다. (10점)
7. 학생점수를 수정한다. 점수를 수정할 경우 총점, 평균을 계산하여 같이 저장한다. (10점)
8. 학생점수를 삭제한다. (10점)
9. DAO, DTO를 작성한다. (10점)
10. View를 이용하여 데이터를 불러온다. (10점)

* 아래 내용을 확인해주세요. (아래 내용이 작성되지 않을 경우 부분 감점)
1. 모든 키는 "학번" 필드를 사용. (학생테이블의 학번은 기본키로, 점수테이블의 학번은 외래키로 등록한다.)
2. 소스코드에는 각 프로그램 라인을 설명할 수 있는 주석문을 자세하게 작성

* 제출방법
모든 파일(소스파일, SQL스크립트 파일)을 압축하여 업로드합니다.

* 각 문제의 부분 점수는 아래와 같습니다.
상(10점), 중(7점), 하(5), 에러(3)


최초 풀이 및 오류 부분 파악

 

student 테이블과  score 테이블의 연결될 key인 학번을 'std_num'으로 동일하게 작성했어야 함.

(std_num과 scr_num으로 따로 작성하면 안되었음.)

 

regdate 필드는 참고 코드와 같이 datetime default now() 로 작성하는 것이 더 확인하기 편함.

 

 
# 0 . mysqlclient 설치 및 cursor 지정

!pip install mysqlclient

import MySQLdb

db = MySQLdb.connect('localhost','root','1234','kdt') # table을 가져올 db의 계정 정보
cur = db.cursor() # 커서 지정
 

참고 코드는 이 부분을 DAO 파트에 작성함.

 

 
# 1. DTO class 작성

class Student: # Student class 지정
   
    def __init__(self, std_num, std_name, std_hp, std_email, std_add): # 생성자 지정
        self.std_num = std_num
        self.std_name = std_name
        self.std_hp = std_hp
        self.std_email = std_email
        self.std_add = std_add

    def getStd_num(self): # std_num의 반환
        return self.std_num

    def getStd_name(self): # std_name의 반환                                                    
        return self.std_name

    def getStd_hp(self): # std_hp의 반환                                                        
        return self.std_hp

    def getStd_email(self): # std_email의 반환                                                
        return self.std_email

    def getStd_add(self):  # std_add의 반환                                                
        return self.std_add
       
       
class Score: # Score class 지정
   
    def __init__(self, scr_num, scr_java, scr_python, scr_c, scr_sum, scr_avg):  # 생성자 지정
        self.scr_num = scr_num
        self.scr_java = scr_java
        self.scr_python = scr_python
        self.scr_c = scr_c
        self.scr_sum = int(scr_java) + int(scr_python) + int(scr_c)
        self.scr_avg = float(self.scr_sum) / 3
       
    def getScr_num(self):   # scr_num의 반환                                                      
        return self.scr_num
   
    def getScr_java(self):  # scr_java의 반환                                                          
        return self.scr_java

    def getScr_python(self):   # scr_python의 반환                                          
        return self.scr_python

    def getScr_c(self):      # scr_c의 반환                                                  
        return self.scr_c

    def getScr_sum(self):    # scr_sum의 반환                                                      
        return self.scr_java + self.scr_python + self.scr_c

    def getScr_avg(self):    # scr_avg의 반환                                                          
        return (self.scr_java + self.scr_python + self.scr_c)/3
 

getter 메소드만 작성했으나, 참고 코드에는 setter 메소드까지 같이 작성이 되어있음.

Score class의 변수로는 scr_num이 아니라 std_num으로 Student class와 통일시켜야 했음.

또한, 참고 코드는 scr_sum과 scr_avg의 연산을 DTO가 아닌 Service의 scrUpdate() 메소드에 작성함.

 

 
student = Student("1000","김사과","010-1111-1111","apple@fow.kr","서울") # 변수 student의 정의
score = Score("1000","40","50","60","150","50") # 변수 score의 정의
 

 

 
# 2. DAO class 작성

class StudentDao: # StudentDao class 지정
   
    def __init__(self): # 생성자 지정
        self.db = None
       
    def connect(self): # db와의 연결 메서드 지정
        self.db = MySQLdb.connect('localhost', 'root', '1234', 'kdt')
       
    def disconnect(self): # db와의 연결해제 메서드 지정
        self.db.close()
       
    def insert_std(self, students): # students를 매개변수로 한 insert_std 메서드 지정. sql의 student table에 data를 삽입.
        self.connect()
        cur = self.db.cursor()
        sql = "insert into student(std_num, std_name, std_hp, std_email, std_add) values (%s, %s, %s, %s, %s)"
        data = (students.getStd_num, students.getStd_name, students.getStd_hp, students.getStd_email, students.getStd_add)
        cur.execute(sql, data)
        self.db.commit()
        self.disconnect()
       
    def insert_scr(self, scores): # scores를 매개변수로 한 insert_scr 메서드 지정. sql의 score table에 data를 삽입.
        self.connect()
        cur = self.db.cursor()
        sql = "insert into score(scr_num, scr_java, scr_python, scr_c, scr_sum, scr_avg) values (%s, %s, %s, %s, %s, %s)"
        data = (scores.getScr_num(), scores.getScr_java(), scores.getScr_python(), scores.getScr_c(), scores.getScr_sum(), scores.getScr_avg())
        cur.execute(sql, data)
        self.db.commit()
        self.disconnect()
       
    def selectAll(self): # selectAll 메서드 지정. student와 score table을 join한 data를 모두 불러옴.
        self.connect()
        cur = self.db.cursor()
        sql = "select * from vw_student_score"
        data = (f'학번:{row[0]}\n이름:{row[1]}\n전화번호:{row[2]}\n이메일:{row[3]}\n주소:{row[4]}\nJAVA점수:{row[5]}\nPython점수:{row[6]}\nC점수:{row[7]}\n합계:{row[8]}\n평균:{row[9]}\n')
        cur.execute(sql, data) # sql 조건지정 : 평균점수로 내림차순 + 학번으로 내림차순
        row = cur.fetchall()
        self.disconnect()

    def search(self, std_num): #search 메서드 지정. std_num을 매개변수로 하여 student와 score table을 join한 data를 검색.
        self.connect()
        cur = self.db.cursor()
        sql = "select * from vw_student_score where std_num=%s"
        cur.execute(sql, (std_num,))
        row = cur.fetchone()
        if row is None:
            print("해당 학생이 존재하지 않습니다.")
        else:
            print("학번: {}\n이름: {}\n연락처: {}\n이메일: {}\n주소: {}".format(row[0], row[1], row[2], row[3], row[4]))
        self.disconnect()
       
    def update_std(self, students): #update_std 메서드 지정. students를 매개변수로 하여 std_num으로 나머지 data를 수정.
        self.connect()
        cur = self.db.cursor()
        sql = "update student set std_name=%s, std_hp=%s, std_email=%s, std_add=%s where std_num=%s"
        data = (students.getStd_num(), students.getStd_name(), students.getStd_hp(), students.getStd_email(), students.getStd_add())
        cur.execute(sql, data)
        self.db.commit()
        self.disconnect()
       
    def update_scr(self, scores): #update_scr 메서드 지정. scores를 매개변수로 하여 scr_num으로 나머지 data를 수정.
        scr_sum = score.getScr_java() + score.getScr_python() + score.getScr_c()
        scr_avg = scr_sum / 3
        self.connect()
        cur = self.db.cursor()
        sql = "update score set scr_java=%s, scr_python=%s, scr_c=%s, scr_sum=%s, scr_avg=%s where scr_num=%s"
        data = (scores.getScr_num(), scores.getScr_java(), scores.getScr_python(), scores.getScr_c(), scores.getScr_sum(), scores.getScr_avg())
        cur.execute(sql, data)
        self.db.commit()
        self.disconnect()
       
    def delete_std(self, std_num): #delete_std 메서드 지정. std_num을 매개변수로 하여 std_num으로 정보 및 점수를 포함한 data를 삭제.
        self.connect()
        cur = self.db.cursor()
        sql = "delete from student where std_num=%s"
        cur.execute(sql, (std_num,))
        sql = "delete from score where std_num=%s"
        cur.execute(sql, (std_num,))
        self.db.commit()
        self.disconnect()
       
    def delete_scr(self, scr_num): #delete_std 메서드 지정. scr_num을 매개변수로 하여 scr_num으로 점수 data를 삭제.
        self.connect()
        cur = self.db.cursor()
        sql = "delete from score where scr_num=%s"
        cur.execute(sql, (scr_num,))
        self.db.commit()
        self.disconnect()
 
 

 

1.  insert_std 메서드:

     Score class에 학번을 입력하는 SQL문을 추가해주어야 함.

     기존에 작성한 sql을 sql1로 변수 변경을 해주고, sql2를 추가.

      sql2 = "insert into Score(std_num) values (%s)" 

    해당 SQL문에 대한 data, cursor의 excute코드도 추가 작성 필요.

      data2 = (data.getStd_num(),)

      cur.execute(sql2, data2)

 

2. insert_scr 메서드:

    sql문, data의 scr_num을 모두 std_num으로 변경.

 

3. selectAll 메서드:

    sql문에 내림차순에 대한 조건 누락.

    sql = "select * from vw_student_score order by scr_avg desc, std_num desc"

   search 메서드에서의 변수 row와 동일한 이름을 사용

   row_selectAll과 row_search로 변경 필요.

   데이터베이스를 확정하는 코드 및 row를 반환하는 코드의 누락.

    row_selectAll = cur.fetchall()

    self.db.commit()

    return row_selectAll

 

4. search 메서드 작성.

   selectAll 메서드에서의 변수 row와 동일한 이름을 사용.

   row_selectAll과 row_search로 변경 필요.

   row_search = cur.fetchone()

   row를 반환하는 코드의 누락.

   return row_search

 

5. update_std 작성

가져올 테이블을 student에서 vw_student_score로 sql문 변경.

sql = "update vw_student_score set std_name=%s, std_hp=%s, std_email=%s, std_add=%s where std_num=%s"
update_scr 메서드 삭제

 

6. delete_std 메서드 작성

    2개의 sql문의 변수를 동일한 이름을 사용.

    sql1과 sql2로 변경 필요.

    (score table이 student table에서 참조가 되는 table의 관계이므로, score table에서의 삭제가 먼저 이루어져야 한다.)

   해당 SQL문에 대한 data, cursor의 excute코드도 추가 작성 필요.

   sql2 = "delete from score where std_num=%s"
   cur.execute(sql2, (std_num,))

   sql1 = "delete from student where std_num=%s"
   cur.execute(sql1, (std_num,))

 

7. delete_scr 메서드 작성

 '성적을 삭제할 때 같이 삭제된 학번만을 되살리는 작업이 필요' 

 SQL문 및 cursor의 execute 코드 2개씩 작성 (scr_num → std_num)

 sql1 = "delete from score where std_num=%s"

 cur.execute(sql1, (std_num,))

 sql2 = "insert into score(std_num) values (%s) "

 cur.execute(sql2, (std_num,))

 

# 3. Service class 작성
   
class StudentService: # StudentService class 지정

    def __init__(self):  # 생성자 지정
        self.dao = StudentDao()

    def stdInsert(self): # stdinsert 메서드 지정. input으로 각 data를 입력받아 insert_std에 넘김.
        std_num = input('학번을 입력하세요:')
        std_name = input('이름을 입력하세요:')
        std_hp = input('연락처를 입력하세요[010-0000-0000]:')
        std_email = input('이메일을 입력하세요:')
        std_add = input('주소를 입력하세요:')
        students = Student(std_num, std_name, std_hp, std_email, std_add)
        self.dao.insert_std(students)
   
    def scrInsert(self):     # scrinsert 메서드 지정. input으로 각 data를 입력받아 insert_scr에 넘김.
        scr_num = input('학번을 입력하세요:')
        scr_java = input('JAVA 점수를 입력하세요:')
        scr_python = input('Python 점수를 입력하세요:')
        scr_c = input('C언어 점수를 입력하세요:')
        scr_sum = int(scr_java) + int(scr_python) + int(scr_c)
        scr_avg = float(scr_sum) / 3
        scores = Score(scr_num, scr_java, scr_python, scr_c, scr_sum, scr_avg)
        self.dao.insert_scr(scores)
        print(scores)
       
    def printAll(self): # printAll 메서드 지정.
        datas = self.dao.selectAll()
        print(datas) # selectAll메서드에서 일치하는 datas를 모두 가져와서 print.
        print("등록된 학생 수 : ", len(datas), "명") # 등록된 전체 학생의 수 print.
        rank = 1 # 석차 print.
        for i in range(len(datas)):
            if i > 0 and datas[i].getScr_avg() < datas[i-1].getScr_avg():
                rank += 1
            datas[i].setRank(rank)
        for j in datas:
            print(f'{rank}등: 학번({j.getScr_num()}), 평균({j.getScr_avg()})')
     
    def Search(self): #Search 메서드 지정. std_num을 입력받아 search메서드에서 일치하는 data를 가져와서 print.
        std_num = input('검색할 학생정보에 대한 학번을 입력하세요:')
        data = self.dao.search(std_num)
        print(data)
       
    def stdUpdate(self): #stdUpdate 메서드 지정. std_num을 입력받아 search 및 update_std메서드에서 일치하는 data를 가져와서 나머지 data를 수정.
            std_num = input('수정할 정보에 대한 학번을 입력하세요:')
            data = self.dao.search(std_num)
            std_name = input('수정할 학생명을 입력하세요:')
            std_hp = input('수정할 연락처를 입력하세요:')
            std_email = input('수정할 이메일을 입력하세요:')
            std_add = input('수정할 주소를 입력하세요:')
            students = Student(std_num, std_name, std_hp, std_email, std_add)
            self.dao.update_std(students)            
           
    def scrUpdate(self): #scrUpdate 메서드 지정. scr_num을 입력받아 search 및 update_scr메서드에서 일치하는 data를 가져와서 나머지 data를 수정.
            scr_num = input('수정할 점수에 대한 학번을 입력하세요:')
            data = self.dao.search(scr_num)
            scr_java = input('수정할 JAVA 점수를 입력하세요:')
            scr_python = input('수정할 Python 점수를 입력하세요:')
            scr_c = input('수정할 C언어 점수를 입력하세요:')
            scores = Score(scr_java, scr_python, scr_c, scr_sum, scr_avg)
            self.dao.update_scr(scores)

    def stdDel(self): #stdDel 메서드 지정. std_num을 입력받아 delete_std메서드에서 일치하는 data를 삭제.
        std_num = input('삭제할 정보에 대한 학번을 입력하세요:')
        self.dao.delete_std(std_num)
       
    def scrDel(self): #scrDel 메서드 지정. scr_num을 입력받아 delete_scr메서드에서 일치하는 data를 삭제.
        scr_num = input('삭제할 점수에 대한 학번을 입력하세요:')
        self.dao.delete_scr(scr_num)
 

 

1. printAll 서비스

if문과 for문을 이용한 석차의 작성.

idx = 0

no = 1

if datas:

    for students in datas

       print(f'석차:[{no}] {students[idx]}, {students[idx+1]}, {students[idx+2]}, {students[idx+3]}, {students[idx+4]},  {students[idx+5]}, {students[idx+6]}')
                no += 1
else :
      print('데이터가 존재 하지 않습니다. ')

 

 

2. Search 서비스

while문과 if문을 이용하여 검색 서비스 작성.

while True:
    std_num = input('검색할 학번을 입력해주세요. ')
    data = self.dao.search(std_num)             
    if data == None:
         print(f'학번 {std_num} 찾을수 없습니다. 다시 입력해주세요. ')
    else:
         print (f'학번 :{data[0]}, 학생명 :{data[1]}, 연락처 :{data[2]}, 이메일 :{data[3]}, 주소 :{info[4]}\n평균 :{info[5]}, 총점 :{info[6]} ')
         break

 

 

3. stdUpdate 서비스

if문을 이용하여 업데이트 서비스 작성.

std_num = input('수정할 학번을 입력해주세요. ')         
data = self.dao.search(std_num)                # 입력 받은 학번을 찾기 
if data == None:
     print(f'{std_num} 학번을 찾을수 없습니다. ')            
else:           
     std_name= input('수정할 이름을 입력해주세요. ')
     std_hp= input('수정할 연락처를 입력해주세요. ')
     std_email= input('수정할 이메일을 입력해주세요. ')
     std_add= input('수정할 주소를 입력해주세요. ')             
     print (f'입력한 값 :학번: {std_num } 이름:{std_name}, 번호:{std_hp}, 이메일:{std_email}, 주소:{std_add}')
     students = Student(std_num , std_name, std_hp, std_email, std_add)

    self.dao.update_std(students)

 

 

4. stdDel 서비스
if문을 이용하여 학생정보 삭제 서비스 작성.
std_num= input('삭제할 학번을 입력해주세요. ')       
data = self.dao.search(std_num)               # 입력 받은 학번을 찾기 
if data == None:
     print(f'{std_num} 학번을 찾을수 없습니다. ')
else:            
     self.dao.delete_std(std_num

 

 

5. scrUpdate 서비스

if문을 이용하여 학생점수 입력 및 수정 서비스 작성.

avg, sum의 연산을 이 메서드에 입력.

std_num= input('수정할 점수에 대한 학번을 입력하세요:')
data = self.dao.search(std_num)          # 입력 받은 학번을 찾기 

 if data == None:
            print(f'{std_num} 학번을 찾을수 없습니다. ')             
else:
            scr_java = input('수정할 JAVA 점수를 입력하세요:')
            scr_python = input('수정할 Python 점수를 입력하세요:')
            scr_c = input('수정할 C언어 점수를 입력하세요:')       
            scr_sum= scr_java+ scr_python+ scr_c      #입력 받은값 연산 
            scr_avg= scr_sum/3         
            scores = Score(scr_java, scr_python, scr_c, scr_sum, scr_avg)    # DTO에서 객체를 생성하기            
            self.dao.update_scr(scores)    # DAO로 값 넘겨주기 

 

 

6. scrDel 서비스

if문을 이용하여 학생점수 삭제 서비스 작성.        

stdDel 메서드 삭제

std_num = input('삭제할 점수의 학번을 입력해주세요. ')
data = self.dao.delete_scr(std_num)
if data == None:
      print(f'{std_num} 학번을 찾을수 없습니다. ')
else:
      self.dao.del_scr(std_num)

 

 

 
# 4. Menu class 작성

class Menu: # Menu class 지정
 
    def __init__(self): # 생성자 지정
        self.service = StudentService()
   
    def run(self): # run이라는 메서드 지정. menu 및 하위의 scr메뉴에서 본인이 시도하고자 하는 내용의 숫자를 입력하여 Service class의 메서드로 이동.
        while True: # While문으로 반복을 요청 후 '7'을 선택할 시 반복을 중단.
            try: # try-except문을 통해 오류가 발생할 시 숫자의 재입력을 요청.
                menu = int(input('1. 학생정보등록 \n2. 학생정보출력 \n3. 학생정보검색 \n4. 학생정보수정 \n5. 학생정보삭제 \n6. 학생점수 \n7. 종료 \n'))
                if menu == 1:
                    self.service.stdInsert() # 1번 학생정보등록으로, Service class의 stdInsert()를 시행.          
                elif menu == 2:
                    self.service.printAll() # 2번 학생정보출력으로, Service class의 printAll()를 시행.
                elif menu == 3:
                    self.service.Search() # 3번 학생정보검색으로, Service class의 Search()를 시행.
                elif menu == 4:
                    self.service.stdUpdate() # 4번 학생정보수정으로, Service class의 stdUpdate()를 시행.
                elif menu == 5:
                    self.service.stdDel() # 5번 학생정보삭제로, Service class의 stdDel()를 시행.
                elif menu == 6:
                    scrmenu = int(input('1. 학생점수등록 \n2. 학생점수수정 \n3. 학생점수삭제 \n4. 종료'))
                    if scrmenu == 1:
                        self.service.scrInsert() # 1번 학생점수등록으로, Service class의 scrInsert()를 시행.
                    elif scrmenu == 2:
                        self.service.scrUpdate() # 2번 학생점수수정으로, Service class의 scrUpdate()를 시행.  
                    elif scrmenu == 3:
                        self.service.scrDel() # 3번 학생점수삭제로, Service class의 scrDel()를 시행.    
                    elif scrmenu == 4:
                        break # 4번 선택 시 해당 반복 중단.
                elif menu == 7:
                    break # 7번 선택 시 해당 반복 중단.
            except Exception as e:
                print(e)
                print('다시 입력하세요.') # 오류 발생 시 해당 문구 출력.
 

 

run 메서드

Service의 메서드 갯수 7개 + 종료 1개로 총 8개의 항목 구성 필요.

        while True:
            menu = int(input('1. 학생정보등록| 2. 학생정보출력| 3.학생정보검색| 4.학생정보수정| 5.학생정보삭제| 6.학생 점수 입력및수정 \n| 7.학생점수삭제 | 8.종료'))
            if menu == 1:
                self.service.stdInsert()               
            elif menu == 2:
                self.service.printAll()                 
            elif menu == 3:
                self.service.Search()                
            elif menu == 4:
                self.service.stdUpdate()                 
            elif menu == 5:
                self.service.stdDel()                   
            elif menu == 6:
                self.service.scrUpdate()                 
            elif menu == 7:
                self.service.scrDel()                        
            elif menu == 8:
                break
    

 
# 5. Menu class 실행

start = Menu()
start.run()
 

 


정답 풀이 참고

 

 
#DTO

# (학생 테이블 필드 : 학번, 이름, 연락처, 이메일, 주소) 5개 (studentno, studentname, hp, email, address)
class studentInfor:
    def __init__(self, studentno, studentname, hp, email, address) :
        self.studentno = studentno
        self.studentname = studentname
        self.address = address
        self.hp = hp
        self.email = email
        self.address = address
       
       
                 #  입력 받은 학번
    def setStudentno(self, studentno):
        self.studentno = studentno
    def getStudentno(self):
        return self.studentno
                #  입력 받은 이름
    def setStudentname(self, studentname):
        self.studentname = studentname
    def getStudentname(self):
        return self.studentname
                #  입력 받은 연락처
    def setHp(self, hp):
        self.hp = hp
    def getHp(self):
        return self.hp
                #  입력 받은 이메일
    def setEmail(self, email):
        self.email = email
    def getEmail(self):
        return self.email
                #  입력 받은 주소
    def setAddress(self, address):
        self.address = address
    def getAddress(self):
        return self.address
   
# (성적 테이블 필드 : 자바 점수 파이썬 점수 C언어 점수 평균 총합 학점 ) 5개 (java, py, cl, ave, total, studentno)
class gradesInfo:
    def __init__(self, java, py, cl, ave, total, studentno):
        self.java = java
        self.py = py
        self.cl = cl
        self.ave = ave
        self.total = total
        self.studentno = studentno
       
       
    def setJava(self, java):
        self.java = java
    def getJava(self):
        return self.java
       
    def setPy(self, py):
        self.py = py
    def getPy(self):
        return self.py
 
    def setCl(self, cl):
        self.cl = cl
    def getCl(self):
        return self.cl
   
    def setAve(self, ave):
        self.ave = ave
    def getAve(self):
        return self.ave
   
    def setTotal(self, total):
        self.total = total
    def getTotal(self):
        return self.total
   

    def setStudentno(self, studentno):
        self.studentno = studentno
    def getStudentno(self):
        return self.studentno
 
 #DAO

'''
1. 학생 등록
2. 학생 정보 성적으로 내림차순 출력
3. 정보 수정 (학번입력받기)
4. 정보 검색 (학번입력받기)
6. 학생 점수 등록 (총점, 평균 계산해서 입력받기)
7. 학생 점수 수정 (총점, 평균 계산해서 입력받기)
8. 학생 점수 삭제
9. 종료

'''

import MySQLdb

class studentDao:
    def __init__(self):
        self.db = None

       
       
    # 데이터 베이스 연동
    def connect(self):
        self.db = MySQLdb.connect('localhost','root','1234','kdt')
    #데이터 베이스 닫기
    def disconnect(self):
        self.db.close()
       
    # 1. 학생 정보 입력받기
    # (학생 테이블 필드 : 학번, 이름, 연락처, 이메일, 주소) 5개
    #studentno, studentname, hp, email, address
    def insert(self, data):
       
        self.connect()
        cur = self.db.cursor()
        sql = "insert into student(studentno, studentname, hp, email, address) values(%s, %s, %s, %s, %s)"
        Gsql = "insert into grades(studentno) values(%s)"
        datas = (data.getStudentno(), data.getStudentname(), data.getHp(), data.getEmail(), data.getAddress())
        Gdata = (data.getStudentno(),)

       
        cur.execute(sql, datas)
        cur.execute(Gsql, Gdata)
       
        self.db.commit()
        self.disconnect()
       
    #2. 전체 출력
    def printS(self):
       
        self.connect()
        cur = self.db.cursor()
        sql = "select * from vw_student order by ave desc, studentno desc" # 평균 값과 학번으로 내림차순정리
       
        cur.execute(sql)
        st_list = cur.fetchall()
       
        self.db.commit()
        self.disconnect()
        return st_list
   
    #3. 업데이트
    def updataS(self, data):
       
        self.connect()
        cur = self.db.cursor()
       
        # 데이터의 값을 입력 받아저장하기
        datas = (data.getStudentname(), data.getHp(), data.getEmail(), data.getAddress(), data.getStudentno())
        sql = "update vw_student set studentname = %s, hp = %s, email = %s, address = %s where studentno = %s"
        print(datas)
        cur.execute(sql, datas)
        self.db.commit()
        self.disconnect()
       
       
       
    #4. 검색 - 입력 받은 학번으로 데이터베이스의 뷰를 통해 답 찾아오기
    def searchS(self, studentno):
       
        self.connect()
        cur = self.db.cursor()
        sql = "select * from vw_student where studentno = %s "
        num =  (studentno,)
               
        cur.execute(sql, num)
        info = cur.fetchone() # 데이터베이스의 결과값 1개만 받아오려고 fetchone사용
       
        self.db.commit()
        self.disconnect()
       
        return info
   
   
    # 5. 정보 삭제
   
    def deleteS(self, studentno):
       
        self.connect()
        cur = self.db.cursor()
        Gsql = "delete from grades where studentno = %s"
        sql = "delete from student where studentno = %s"
       
        num =  (studentno,)
       
        cur.execute(Gsql, num)
        cur.execute(sql, num)
       
        self.db.commit()
        self.disconnect()
   
    # 6. 성적 테이블에 값 추가
    # 글로벌 변수를 사용하여 float형태로 입력 받기
   
    def gradesInsertS(self, data):
        #global java,py,cl
       
        self.connect()
        cur = self.db.cursor()
               
        sql = "update grades set java= %s, py = %s, cl = %s, ave = %s, total = %s where studentno = %s"
       
        datas = (data.getJava(), data.getPy(), data.getCl(), data.getAve(), data.getTotal(), data.getStudentno())
        print(datas)
       
        cur.execute(sql, datas)
       
        self.db.commit()
        self.disconnect()
       
       
       
    # 7. 성적 삭제
   
    def gradesdeleteS(self, studentno):
        self.connect()
        cur = self.db.cursor()
        #성적 테이블에 입력받은 학번 전체 삭제
        Gsql = "delete from grades where studentno = %s"
        num =  (studentno,)
        cur.execute(Gsql, num)
       
        # 성적을 삭제 할때 위같이 하면 학번까지 지워져 버려서 학번을 다시 입력 하기
        sql = "insert into grades(studentno) values(%s)"
        cur.execute(sql, num)
       
       
        self.db.commit()
        self.disconnect()
   
       
 
# 서비스

'''
1. 학생 등록
2. 학생 정보 성적으로 내림차순 출력
3. 정보 수정 (학번입력받기)
4. 정보 검색 (학번입력받기)
6. 학생 점수 등록 (총점, 평균 계산해서 입력받기)
7. 학생 점수 수정 (총점, 평균 계산해서 입력받기)
8. 학생 점수 삭제
9. 종료

'''

class studentService:
   
    def __init__(self):
        self.dao = studentDao()
       
       
    # 1. 등록 해주는 서비스    
    def insertInfo(self):
       
        studentno = input('학번을 입력해주세요. ')
        studentname = input('이름을 입력해주세요. ')
        hp = input('핸드폰번호를 입력해주세요. ')
        email = input('이메일을 입력해주세요. ')
        address = input('주소를 입력해주세요. ')
       
        # 입력 받은 값을 DAO에 값을 전달 하기 위한 DTO
        data = studentInfor(studentno, studentname, hp, email, address)
       
        # DTO에서 받은 값을 data담고 DAO에게 전달
        self.dao.insert(data)
       
       
        # 2. 내용 출력 서비스
    def printAll(self):
       
        print('석차, 학번, 이름, 번호, 메일, 주소, 평균, 총합')
        print('='*50)
       
        datas = self.dao.printS()
        idx = 0
        no = 1
       
        if datas :
            for data in datas:
                # 학번 이름 번호 메일 주소 평균 총합
                print(f'석차:[{no}] {data[idx]}, {data[idx+1]}, {data[idx+2]}, {data[idx+3]}, {data[idx+4]},  {data[idx+5]}, {data[idx+6]}')
                no += 1
        else :
            print('데이터가 존재 하지 않습니다. ')
           
     
        #3. 검색 서비스
    def searchInfo(self):
       
        while True:
            studentno = input('검색할 학번을 입력해주세요. ')
            print ('='*50)
            info = self.dao.searchS(studentno)
           
            if info == None:
                print(f'학번 {studentno} 찾을수 없습니다. 다시 입력해주세요. ')
            else:
                print (f'학번 :{info[0]}, 학생명 :{info[1]}, 학생H.P :{info[2]}, 학생 e-Mail :{info[3]}, 주소 :{info[4]}\n평균 :{info[5]}, 총점 :{info[6]} ')
                break
               
        #4. 업데이트 서비스
    def updataInfo(self):
       
        studentno = input('변경할 학번을 입력해주세요. ')
       
        info = self.dao.searchS(studentno)
               

        if info == None:
            print(f'{studentno} 학번을 찾을수 없습니다. ')
           
        else:
           
            studentname = input('변경할 이름을 입력해주세요. ')
            hp = input('변경할 핸드폰번호를 입력해주세요. ')
            email = input('변경할 이메일을 입력해주세요. ')
            address = input('변경할 주소를 입력해주세요. ')
           
            print (f'입력한 값 :학번: {studentno} 이름:{studentname}, 번호:{hp}, 이메일:{email}, 주소:{address}')
            data = studentInfor(studentno, studentname, hp, email, address)

            self.dao.updataS(data)
           
           

        # 5. 학생 정보 삭제 서비스
        # 학번을 입력 받아 검색후
    def delete(self):
       
        studentno = input('변경할 학번을 입력해주세요. ')
        # 입력 받은 학번을 찾기
        info = self.dao.searchS(studentno)
             

        if info == None:
            print(f'{studentno} 학번을 찾을수 없습니다. ')
        else:
           
             self.dao.deleteS(studentno)
           
        # 6.7 성적을 입력 받는 서비스
    def gradesUpdata(self):
       
        studentno = input('변경할 학번을 입력해주세요. ')
       
        info = self.dao.searchS(studentno)
               

        if info == None:
            print(f'{studentno} 학번을 찾을수 없습니다. ')
           
        else:
           
            java = float(input('자바 점수 '))
            py = float(input('파이썬 점수 '))
            cl = float(input('C언어 점수 '))

            #입력 받은값 연산
            total = java + py + cl
            ave = total/3

            # DTO에서 객체를 생성하기
            data = gradesInfo(java, py, cl, ave, total, studentno)
            # DAO로 값 넘겨주기
            self.dao.gradesInsertS(data)

       
        # 8. 성적 삭제 서비스
    def gradesDe(self):
       
        studentno = input('변경할 학번을 입력해주세요. ')
       
        info = self.dao.searchS(studentno)
               

        if info == None:
            print(f'{studentno} 학번을 찾을수 없습니다. ')
        else:
            self.dao.gradesdeleteS(studentno)
               


class Menu():
    def __init__(self):
        self.service = studentService()
   
    def run(self):
       
       
        while True:
            print('='*50)
            menu = int(input('1. 학생등록| 2. 전체 학생| 3.학생정보 수정| 4.학생정보 검색| 5.학생 정보 삭제| 6.학생 점수 입력 \n| 7.학생 점수 수정 | 8.학생 점수 삭제| 9.종료'))
            print('='*50)
            if menu == 1:
                self.service.insertInfo()
               
            elif menu == 2:
                self.service.printAll()
               
            elif menu == 3:
                self.service.updataInfo()
               
            elif menu == 4:
                self.service.searchInfo()
               
            elif menu == 5:
                self.service.delete()  
               
            elif menu == 6:
                self.service.gradesUpdata()
               
            elif menu == 7:
                self.service.gradesUpdata()      
               
            elif menu == 8:
                self.service.gradesDe()
               
            if menu == 9:
               
                break
   
 
start = Menu()
start.run()
 

수정한 풀이

 


# 0 . mysqlclient 설치 및 cursor, 변수 지정

!pip install mysqlclient

import MySQLdb

db = MySQLdb.connect('localhost','root','1234','kdt') # table을 가져올 db의 계정 정보
cur = db.cursor() # 커서 지정

student = Student("1000","김사과","010-1111-1111","apple@fow.kr","서울") # 변수 student의 정의
score = Score("1000","40","50","60","150","50") # 변수 score의 정의

# 1. DTO class 작성

class Student: # Student class 지정
    
    def __init__(self, std_num, std_name, std_hp, std_email, std_add): # 생성자 지정
        self.std_num = std_num
        self.std_name = std_name
        self.std_hp = std_hp
        self.std_email = std_email
        self.std_add = std_add

    def getStd_num(self): # std_num의 반환
        return self.std_num

    def getStd_name(self): # std_name의 반환                                                    
        return self.std_name

    def getStd_hp(self): # std_hp의 반환                                                         
        return self.std_hp

    def getStd_email(self): # std_email의 반환                                                 
        return self.std_email

    def getStd_add(self):  # std_add의 반환                                                 
        return self.std_add
        
        
class Score: # Score class 지정
    
    def __init__(self, std_num, scr_java, scr_python, scr_c, scr_sum, scr_avg):  # 생성자 지정
        self.std_num = std_num
        self.scr_java = scr_java
        self.scr_python = scr_python
        self.scr_c = scr_c
        self.scr_sum = scr_sum
        self.scr_avg = scr_avg
        
    def getStd_num(self):   # std_num의 반환                                                      
        return self.std_num
    
    def getScr_java(self):  # scr_java의 반환                                                          
        return self.scr_java

    def getScr_python(self):   # scr_python의 반환                                          
        return self.scr_python

    def getScr_c(self):      # scr_c의 반환                                                   
        return self.scr_c

    def getScr_sum(self):    # scr_sum의 반환                                                      
        return self.scr_sum

    def getScr_avg(self):    # scr_avg의 반환                                                           
        return self.scr_avg

# 2. DAO class 작성

class StudentDao: # StudentDao class 지정 
    
    def __init__(self): # 생성자 지정
        self.db = None
        
    def connect(self): # db와의 연결 메서드 지정
        self.db = MySQLdb.connect('localhost', 'root', '1234', 'kdt')
        
    def disconnect(self): # db와의 연결해제 메서드 지정
        self.db.close()
        
    def insert_std(self, data): # 1. 학생정보 입력
        self.connect()
        cur = self.db.cursor()
        sql1 = "insert into student(std_num, std_name, std_hp, std_email, std_add) values (%s, %s, %s, %s, %s)"
        sql2 = "insert into score(std_num) values (%s)"
        data1 = (data.getStd_num(), data.getStd_name(), data.getStd_hp(), data.getStd_email(), data.getStd_add())
        data2 = (data.getStd_num(),)
        cur.execute(sql1, data1)
        cur.execute(sql2, data2)
        self.db.commit()
        self.disconnect()
        
    def selectAll(self): # 2. 전체 출력
        self.connect()
        cur = self.db.cursor()
        sql = "select * from vw_student_score order by scr_avg desc, std_num desc"
        cur.execute(sql) # sql 조건지정 : 평균점수로 내림차순 + 학번으로 내림차순
        row = cur.fetchall()
        self.db.commit()
        self.disconnect()
        return row

    def update_std(self, data): # 3. 업데이트
        self.connect()
        cur = self.db.cursor()
        sql = "update vw_student_score set std_name=%s, std_hp=%s, std_email=%s, std_add=%s where std_num=%s"
        data = (data.getStd_num(), data.getStd_name(), data.getStd_hp(), data.getStd_email(), data.getStd_add())
        print(data)
        cur.execute(sql, data)
        self.db.commit()
        self.disconnect()

    def search(self, std_num): # 4. 검색
        self.connect()
        cur = self.db.cursor()
        sql = "select * from vw_student_score where std_num=%s"
        num = (std_num,)
        cur.execute(sql, num)
        row = cur.fetchone()
        self.db.commit()
        self.disconnect()
        return row

    def delete_std(self, std_num): # 5. 정보 삭제
        self.connect()
        cur = self.db.cursor()
        sql1 = "delete from score where std_num=%s"
        sql2 = "delete from student where std_num=%s"
        cur.execute(sql1, (std_num,))
        cur.execute(sql2, (std_num,))
        self.db.commit()
        self.disconnect()
            
    def insert_scr(self, data): # 6. 성적 추가
        self.connect()
        cur = self.db.cursor()
        sql = "update score set scr_java=%s, scr_python=%s, scr_c=%s, scr_sum=%s, scr_avg=%s where std_num=%s"
        data = (data.getStd_num(), data.getScr_java(), data.getScr_python(), data.getScr_c(), data.getScr_sum(), data.getScr_avg())
        print(data)
        cur.execute(sql, data)
        self.db.commit()
        self.disconnect()

    def delete_scr(self, scr_num): # 성적 삭제
        self.connect()
        cur = self.db.cursor()
        sql1 = "delete from score where std_num=%s"
        cur.execute(sql1, (std_num,))
        sql2 = "insert into score(std_num) values(%s)"
        cur.execute(sql2, (std_num,))
        self.db.commit()
        self.disconnect()

# 3. Service class 작성

class StudentService: # StudentService class 지정

    def __init__(self):  # 생성자 지정
        self.dao = StudentDao()

    def stdInsert(self): # 1. 등록 서비스
        std_num = input('학번을 입력하세요:')
        std_name = input('이름을 입력하세요:')
        std_hp = input('연락처를 입력하세요[010-0000-0000]:')
        std_email = input('이메일을 입력하세요:')
        std_add = input('주소를 입력하세요:')
        data = Student(std_num, std_name, std_hp, std_email, std_add)
        self.dao.insert_std(data)
        
    def printAll(self): # 2. 출력 서비스
        datas = self.dao.selectAll()
        idx = 0
        no = 1
        if datas :
            for data in datas: # 학번 이름 번호 메일 주소 평균 총합
                print(f'석차:[{no}] 학번:{data[idx]}, 이름:{data[idx+1]}, 번호:{data[idx+2]}, 메일:{data[idx+3]}, 주소:{data[idx+4]}, 총합:{data[idx+5]}, 평균:{data[idx+6]}')
                no += 1
        else :
            print('데이터가 존재하지 않습니다.')

    def Search(self): # 3. 검색 서비스
        while True:
            std_num = input('검색할 학생정보에 대한 학번을 입력하세요:')
            data = self.dao.search(std_num)
            print(f'학번:{data[0]}, 이름:{data[1]}, 번호:{data[2]}, 메일:{data[3]}, 주소:{data[4]}, 총합:{data[5]}, 평균:{data[6]}')
            break
        
    def stdUpdate(self): # 4. 업데이트 서비스
        std_num = input('수정할 정보에 대한 학번을 입력하세요:')
        data = self.dao.search(std_num)
        if data == None:
            print(f'학번 {std_num}을 찾을 수 없습니다.')
        else :
            std_name = input('수정할 학생명을 입력하세요:')
            std_hp = input('수정할 연락처를 입력하세요:')
            std_email = input('수정할 이메일을 입력하세요:')
            std_add = input('수정할 주소를 입력하세요:')
            print(f'학번:{data[0]}, 이름:{data[1]}, 번호:{data[2]}, 메일:{data[3]}, 주소:{data[4]}, 총합:{data[5]}, 평균:{data[6]}')
            data = Student(std_num, std_name, std_hp, std_email, std_add)
            self.dao.update_std(data)            
            
    def stdDel(self): # 5. 학생정보 삭제 서비스
        std_num = input('삭제할 정보에 대한 학번을 입력하세요:')
        data = self.dao.search(std_num)
        if data == None:
            print(f'{std_num} 학번을 찾을수 없습니다. ')
        else:
            self.dao.delete_std(std_num) 

    def scrUpdate(self): # 6. 7. 학생성적 입력, 수정 서비스
        std_num = input('입력 및 수정할 점수에 대한 학번을 입력하세요:')
        data = self.dao.search(std_num)
        if data == None:
            print(f'{std_num} 학번을 찾을수 없습니다. ')
        else:
            scr_java = float(input('수정할 JAVA 점수를 입력하세요:'))
            scr_python = float(input('수정할 Python 점수를 입력하세요:'))
            scr_c = float(input('수정할 C언어 점수를 입력하세요:'))
            scr_sum = scr_java + scr_python + scr_c
            scr_avg = scr_sum/3
            data = Score(scr_java, scr_python, scr_c, scr_sum, scr_avg, std_num)
            self.dao.insert_scr(data)
        
    def scrDel(self): # 8. 학생성적 삭제 서비스.
        std_num = input('삭제할 점수에 대한 학번을 입력하세요:')
        data = self.dao.search(std_num)
        if data == None:
            print(f'{std_num} 학번을 찾을수 없습니다. ')
        else:
            self.dao.delete_scr(std_num)

# 4. Menu class 작성

class Menu: # Menu class 지정

    def __init__(self): # 생성자 지정
        self.service = StudentService()
    
    def run(self): 
     # run이라는 메서드 지정.
        menu 및 하위의 scr메뉴에서 본인이 시도하고자 하는 내용의 숫자를 입력하여 Service class의 메서드로 이동.
        while True: # While문으로 반복을 요청 후 '8'을 선택할 시 반복을 중단.
            try: # try-except문을 통해 오류가 발생할 시 숫자의 재입력을 요청.
                menu = int(input('1. 학생정보등록 \n2. 학생정보출력 \n3. 학생정보검색 \n4. 학생정보수정 \n5. 학생정보삭제 \n6. 학생점수입력/수정 \n7. 학생점수삭제 \n8. 종료 \n'))
                if menu == 1:
                    self.service.stdInsert() # 1번 학생정보등록으로, Service class의 stdInsert()를 시행.          
                elif menu == 2:
                    self.service.printAll() # 2번 학생정보출력으로, Service class의 printAll()를 시행.
                elif menu == 3:
                    self.service.Search() # 3번 학생정보검색으로, Service class의 Search()를 시행.
                elif menu == 4:
                    self.service.stdUpdate() # 4번 학생정보수정으로, Service class의 stdUpdate()를 시행.
                elif menu == 5:
                    self.service.stdDel() # 5번 학생정보삭제로, Service class의 stdDel()를 시행.
                elif menu == 6:
                    self.service.scrUpdate() # 6번 학생점수입력/수정.
                elif menu == 7:
                    self.service.scrDel() # 7번 학생점수삭제.
                elif menu == 8:
                    break # 8번 종료.
            except Exception as e: 
                print(e)
                print('다시 입력하세요.') # 오류 발생 시 해당 문구 출력.

# 5. Menu class 실행

start = Menu()
start.run()