# if 조건식
# 조건식의 결과가 True일 때 실행문
# else :
# 조건식의 결과가 False일 때 실행문
num = 6
if num >= 0:
print('양수')
else:
print('음수')
2. elif 구문
🐰 세 개이상의 조건을 연결해서 사용하는 조건문
# if 조건식1 :
# 조건식1의 결과가 True일 때 실행문
# elif 조건식2 :
# 조건식1의 결과가 False이고, 조건식2의 결과가 True일 때 실행문
# elif 조건식3 :
# 조건식1, 2의 결과가 False이고, 조건식3의 결과가 True일 때 실행문
# else :
# 조건식1, 2, 3의 결과가 False일 때 실행문
# 나이를 입력받아 7살 이하면 '미취학', 8~13살이면 '초등학생', 14 ~ 16살이면 '중학생',
# 17 ~ 19살이면 '고등학생', 20살 이상이면 '성인'을 출력하는 프로그램입니다.
age = int(input('몇 살입니까? >>> ')) # int() 함수를 이용해서 정수로 변환
if age <= 7:
print('미취학')
elif age <= 13:
print('초등학생')
elif age <= 16:
print('중학생')
elif age <= 19:
print('고등학생')
else:
print('성인')
📌 else 구문과 elif 구문은 이전의 조건이 맞지 않을 때 넘어오는 부분
➡️ 이미 제외된 조건을 한번 더 검사할 필요 없기 때문에 위의 예제와 같이 간단하게 표현 가능
3. pass 키워드
🐰 프로그래밍을 하다 보면 전체 골격을 잡아 놓고 내부에서 처리할 내용은 나중에 채워넣는 경우가 있음
➡️ 이런 경우 if 조건문에 구현 내용을 아무 것도 적어 놓지 않으면 error가 발생함
➡️ 이때'곧 개발하겠음' 이라는 의미로 'pass' 키워드를 넣어주면 error가 발생하지 않는다
# pass 키워드를 사용한 미구현 부분 입력
num = int(input('정수 입력 >>> '))
if num > 0:
# 양수일 때 : 미구현 상태
pass
else:
# 음수일 때 : 미구현 상태
pass
💡 raise NotImplementedError
- 아직 구현하지 부분이라는 의미의 오류를 강제로 발생하게 함
num = int(input('정수 입력 >>> ')
if num > 0:
# 양수일 때
raise NotImplemetedError
else:
# 음수일 때
raise NotImplementedError
👩🏻💻 숫자를 문자열로 변환하는 함수로 중괄호{}를 포함한 문자열 뒤에 마침표(.)를 찍고 format() 함수를 사용
▶️ 중괄호 개수와 format() 함수 괄호 안 매개변수의 개수는 반드시 같아야 함
"{}".format(10)
"{} {}".format(10,20)
📌 위의 구문과 같이 앞쪽에 있는 문자열 {} 기호가 format() 함수 괄호 안에 있는 매개 변수로 차례로 대치되면서 숫자가 문자열로 되는 것
zipcode = '06236'
print('우편번호 : {}'.format(zipcode)) # format() 메서드를 이용해 출력
# 결과) 우편번호 : 06236
zipcode_str = '우편번호 : {}'.format(zipcode)
print(zipcode_str)
# 결과) 우편번호 : 06236
address = '''서울특별시 강남구
테헤란로 146''' # multi line
print('주소 : {addr}'.format(addr=address)) # format() 메서드의 변수 이용
# 결과) 주소 : 서울특별시 강남구
# 테헤란로 146
📌 {} 기호의 개수가 format() 함수의 매개변수 개수보다 많으면 IndexError 예외가 발생
2. format() 함수의 다양한 기능
1) 정수 출력의 다양한 형태
# 정수를 특정 칸에 출력하기
# 정수
num_a = "{:d}".format(52)
# 특정 칸에 출력하기
num_b = "{:5d}".format(52) # 5칸
num_c = "{:10d}".format(52) # 10칸
# 빈칸을 0으로 채우기
num_d = "{:05d}".format(52) # 양수
num_e = "{:05d}".format(-52) # 음수
print('# 기본')
print(num_a)
print('# 특정 칸에 출력하기')
print(num_b)
print(num_c)
print('# 빈칸을 0으로 채우기')
print(num_d)
print(num_e)
📌 {:d}는 int 자료형의 정수를 출력하겠다고 직접적으로 지정하는 것
➡️ 매개변수로 정수만 올 수 있다.
📌 {:5d}는 5칸을 빈칸으로 잡고 뒤에서부터 52라는 숫자를 채운다.
📌 {:05d}는 5칸을 잡고 뒤에서부터 52라는 숫자를 넣은 후 앞의 빈곳을 0으로 채운다.
➡️ 부호가 있을 때는 맨 앞자리를 부호로 채우고 나머지 빈 곳을 0으로 채움
# 기호와 함께 출력하기
num_a = "{:+d}".format(33) # 양수
num_b = "{:+d}".format(-33) # 음수
num_c = "{: d}".format(33) # 양수: 기호 부분 공백
num_d = "{: d}".format(-33)# 음수: 기호 부분 공백
print("# 기호와 함께 출력하기")
print(num_a)
print(num_b)
print(num_c)
print(num_d)
📌 {:+d} 와 같이 d앞에 +기호를 붙이면 양수와 음수 기호를 표현할 수 있다.
📌 {: d} 처럼 앞에 공백을 두어 기호 위치를 비워주면 함수에 입력한 기호가 표현된다.
# < : 지정된 공간 내에서 왼쪽 정렬
# > : 지정된 공간 내에서 오른쪽 정렬
# ^ : 지정된 공간 내에서 가운데 정렬
# 10d는 10자리의 필드 폭을 의미
print("10자리 폭 왼 쪽 정렬 '{:<10d}'".format(123))
# 10자리 폭 왼 쪽 정렬 '123 '
print("10자리 폭 오른 쪽 정렬 '{:>10d}'".format(123))
# 10자리 폭 오른 쪽 정렬 ' 123'
print("10자리 폭 가운데 정렬 '{:^10d}'".format(123))
# 10자리 폭 가운데 정렬 ' 123 '
print()
# 채움문자를 지정하면 공백 대신 채움문자가 빈자리를 채움
print("10자리 폭 왼 쪽 정렬 채움문자 '{:*<10d}'".format(123))
# 10자리 폭 왼 쪽 정렬 채움문자 '123*******'
print("10자리 폭 오른 쪽 정렬 채움문자 '{:*>10d}'".format(123))
# 10자리 폭 오른 쪽 정렬 채움문자 '*******123'
print("10자리 폭 가운데 쪽 정렬 채움문자 '{:*^10d}'".format(123))
# 10자리 폭 가운데 쪽 정렬 채움문자 '***123****'
# 조합하기
num_a = "{:+5d}".format(33) # 기호를 뒤로 밀기: 양수
num_b = "{:+5d}".format(-33) # 기호를 뒤로 밀기: 음수
num_c = "{:=+5d}".format(33) # 기호를 앞으로 밀기: 양수
num_d = "{:=+5d}".format(-33) # 기호를 앞으로 밀기: 음수
num_e = "{:+05d}".format(33) # 0으로 채우기: 양수
num_f = "{:+05d}".format(-33) # 0으로 채우기: 음수
print("# 조합하기")
print(num_a)
print(num_b)
print(num_c)
print(num_d)
print(num_e)
print(num_f)
📌 기호와 공백을 조합할 때 '=' 기호를 앞에 붙일 수 있다.
➡️ 5칸의 공간을 잡았을 때 기호를 빈칸 앞에 붙일 것인지, 숫자 앞에 붙일 것인지 지정
# 부동 소수점 출력의 다양한 형태
num_a = "{:f}".format(12.345)
num_b = "{:15f}".format(12.345) # 15칸 만들기
num_c = "{:+15f}".format(12.345) # 15칸에 부호 추가하기
num_d = "{:+015f}".format(12.345) # 15칸에 부호 추가하고 0으로 채우기
print(num_a)
print(num_b)
print(num_c)
print(num_d)
👩🏻💻 문자열 앞에 'f'를 붙여서 만드는데, 문자열 내부에 표현식을 {} 괄호로 감싸서 삽입할 수 있다.
f'문자열{표현식}문자열'
who = 'you'
how = 'happy'
print(f'{who} make me {how}') # you make me happy / 문자열에 f 또는 F라는 접두어 prefix를 붙임
age = 25
print(f'내년엔 {age + 1}살이 됩니다.') # 내년엔 26살이 됩니다.
📌 format() 함수보다 간단하고 직관적이라 대부분 f-문자열을 사용하는 편
💡 format() 함수를 사용하는 것이 더 좋은 경우
a) 문자열 내용이 너무 많을 때
- f-문자열을 사용하면 어떤 데이터를 삽입하여 출력하는지 확인하기 위해 문자열을 모두 읽어야 하는 문제가 있다.
# 실행되는 모든 한 줄 코드는 문장
print('Hello World!!')
10 + 20
2) 표현식 expression
· 어떠한 값을 만들어 내는 간단한 코드
ex. 숫자, 수식, 문자열
2024
10 + 20 + 30
"Hello Python!!"
3) 키워드 keyword
· 특별한 의미가 부여된 단어로 파이썬이 만들어질 때 이미 사용하겠다고 예약해 놓은 것
· 이름을 정할 때 키워드를 사용하면 안 된다.
· 파이썬은 대소문자를 구분
ex. True는 키워드지만 true는 키워드 x
# 키워드인지 확인하는 방법
import keyword
print(keyword.kwlist)
4) 식별자 identifier
· 이름을 붙일 때 사용하는 단어, 주로 변수 또는 함수 이름 등으로 사용
📌 규칙
a. 키워드를 사용 x
b. 특수 문자는 언더 바(_)만 허용
c. 숫자로 시작 x
d. 공백 포함 x
👾 공백 사용 대신 쓰이는 방법
- 스네이크 케이스 : 단어 사이에 언더 바(_) 기호를 붙여 식별자를 만든다
- 캐멀 케이스 : 단어들의 첫 글자를 대문자로 만들어 식별자를 만든다
👾 식별자 구분하기
- 파이썬에서는 첫 번째 글자를 소문자로 적는 캐멀 케이스는 사용 x
- 캐멀 케이스 ➡️ 클래스 ➡️ 뒤에 괄호가 있으면 클래스 생성자
- 스네이크 케이스 ➡️ 함수 또는 변수 ➡️ 뒤에 괄호가 붙어 있으면 함수, 없으면 변수
5) 주석 comment
· 프로그램의 진행에 전혀 영향을 주지 않는 코드
· 파이썬은 '#' 기호를 붙여 주석 처리
print('Hello World!!')
# 문자열을 작은 따옴표나 큰 따옴표 둘 중 택1 붙여서 사용 가능, 세미콜론 안 붙여도 됨
6) 연산자와 자료
· 연산자는 값과 값 사이에 무언가 기능을 적용할 때 사용하는 것을 말함
ex. +, -
· 리터럴(literal) = 자료 : 숫자이든 문자이든 어떠한 '값' 자체를 의미
7) 출력: print()
· 파이썬의 기본적인 출력 방법
print(출력1, 출력2, ... )
⚡️ 여러 개 출력시 내용을 쉼표로 연결해서 여러개 적으면 된다.
print("안녕하세요", "저의", "이름은", "홍길동입니다!")
# 결과 : 안녕하세요 저의 이름은 홍길동입니다!)
⚡️ print() 함수 괄호 안에 아무것도 입력하지 않으면 단순하게 줄바꿈을 한다.
print("# 아무것도 출력하지 않습니다.")
print("--- 확인 전용선 ---")
print()
print()
print("--- 확인 전용선 ---")
''' 실행결과 )
# 아무것도 출력하지 않습니다.
--- 확인 전용선 ---
--- 확인 전용선 ---
'''
⚡️ 데이터베이스 테이블은 중복과 공간 낭비를 피하고 데이터 무결성을 위해 여러 개 테이블로 분리해 저장
⚡️ 분리된 테이블은 서로 관계 Relation 를 맺고 있는데, 가장 많이 사용하는 관계는 '1대 다' 관계
ex. 학생 한 명이 여러 과목의 학점을 받는 것, 한 개의 아이디로 여러 상품을 주문하는 것
1) INNER JOIN (내부 조인)
SELECT <열 목록>
FROM <첫 번째 테이블>
INNER JOIN <두 번째 테이블>
ON <조인될 조건>
[WHERE 검색조건]
· 첫 번째 테이블은 구매테이블(buytbl), 두 번째 테이블은 회원테이블(usertbl)
SELECT * FROM buytbl
INNER JOIN usertbl
ON buytbl.userID = usertbl.userID
WHERE buytbl.userID = 'JYP';
📌추출 과정
1. 구매 테이블의 userID인 'JYP'를 추출한다.
2. 'JYP'와 동일한 값을 회원 테이블의 userID열에서 검색한 후 찾으면 구매 테이블과 회원 테이블의 두 행을 결합
📌WHERE 절을 생략하면 buytbl 테이블의 모든 행에 대해서 위와 동일한 방식으로 추출
👾필요한 열만 추출하는 방법
SELECT userID, name, prodName, addr, CONCAT(mobile1, mobile2) AS '연락처'
FROM buytbl
INNER JOIN usertbl
ON buytbl.userID = usertbl.userID
ORDER BY num;
📌 위의 구문을 실행하면 다음과 같은 에러 코드가 뜬다.
Error Code: 1052. Column 'userID' in field list is ambiguous
💡 userID의 경우 두 테이블 모두에 들어 있어 어느 테이블의 userID 추출할 지 명시해줘야 함
SELECT buytbl.userID, name, prodName, addr, CONCAT(mobile1, mobile2) AS '연락처'
FROM buytbl
INNER JOIN usertbl
ON buytbl.userID = usertbl.userID
ORDER BY num;
👾 코드가 길어지면 복잡해 보이기 때문에 각 테이블에 '별칭 Alias' 을 부여하는 방법
SELECT B.userID, U.name, B.prodName, U.addr, CONCAT(U.mobile1, U.mobile2) AS '연락처'
FROM buytbl B
INNER JOIN usertbl U
ON B.userID = U.userID
WHERE B.userID = 'JYP';
📌 위와 같이 FROM 절에 나오는 테이블의 이름 뒤에 별칭을 붙여주면 된다.
👾 세 개의 테이블을 조인하는 방법
· 첫 번째 stdTbl(학생테이블) / 두 번째 stdclubTbl / 세 번째 clubTbl
-- 학생 테이블, 동아리 테이블, 학생동아리 테이블을 이용해서 학생을 기준으로 학생 이름/지역/가입한 동아리/동아리방을 출력
SELECT S.stdName, S.addr, C.clubName, C.roomNo
FROM stdTbl S
INNER JOIN stdclubTbl SC
ON S.stdName = SC.stdName
INNER JOIN clubTbl C
ON SC.clubName = C.clubName
ORDER BY S.stdName;
2) OUTER JOIN (외부 조인)
👾주종관계에 있는 테이블에서 주테이블의 모든 레코드를 보여주고 조건을 만족하는 부테이블의 필드를 같이 출력
SELECT <열 목록>
FROM <첫 번째 테이블(LEFT 테이블)>
<LEFT|RIGHT|FULL> OUTER JOIN <두 번째 테이블 (RIGHT 테이블)>
ON <조인될 조건>
[WHERE 검색조건];
📌전체 회원의 구매기록 구하기 (단, 구매 기록 없는 회원도 출력)
SELECT U.userID, U.name, B.prodName, U.addr, CONCAT(U.mobile1, U.mobile2) AS '연락처'
FROM usertbl U
LEFT OUTER JOIN buytbl B -- LEFT OUTER JOIN은 왼쪽 테이블(usertbl)의 것은 모두 출력되어야 한다는 뜻
ON U.userID = B.userID
ORDER BY U.userID;
📌 RIGHT OUTER JOIN을 사용해서 동일한 결과 값을 얻으려면 단순히 왼쪽과 오른쪽 테이블 위치만 바꿔주면 됨
💡 FULL OUTER JOIN (전체 조인) : LEFT JOIN + RIGHT JOIN
➡️ 왼쪽 테이블과 오른쪽 테이블의 모든 행을 반환. 조인 조건에 맞는 데이터가 없는 경우, 해당 테이블의 열에는 NULL 값이 채워짐
3) CROSS JOIN (상호 조인)
👾 한쪽 테이블의 모든 행들과 다른 쪽 테이블의 모든 행을 조인시키는 기능
➡️ 결과 개수는 두 테이블의 개수를 곱한 개수
👾 카티션 곱 Cartesian Product이라고도 부른다.
👾 ON 구문 사용 x, 용도는 테스트로 사용할 많은 용량의 데이터를 생성할 때 주로 사용
📌회원 테이블과 구매 테이블의 CROSS JOIN 구문
SELECT COUNT(*) AS '데이터 개수' FROM buytbl CROSS JOIN usertbl;
4) SELF JOIN (자체 조인)
👾 자기 자신과 자기 자신이 조인한다는 의미
👾 대표적인 예가 조직도와 관련된 테이블
-- 우대리 상관의 연락처를 확인
SELECT A.emp AS '부하직원' , B.emp AS '직속상관', B.empTel AS '직속상관연락처'
FROM empTbl A
INNER JOIN empTbl B
ON A.manager = B.emp
WHERE A.emp = '우대리';
👾 사용자 입력값을 포함해야 할 때는 SQL 문을 변수와 결합해서 만들어야 하므로 코드가 다소 복잡해짐
➡️ 컬럼 수가 많아지면 코드 작성이나 유지보수가 어려움
👾 복잡한 SQL 문을 사용할 때는 Statement의 향상된 기능을 제공하는 PreparedStatement을 사용
③ PreparedStatement
- PreparedStatement는 SQL 문을 미리 만들어 두고 변수를 따로 입력하는 방식
- 기본적으로 Statement 클래스를 상속받기 때문에 Statement 클래스의 메서드를 모두 사용
PreparedStatement pstmt = conn.preparedStatement("insert
into test values(?, ?) ");
pstmt.setString(1, getUserName());
pstmt.setString(2, getEmail());
pstmt.executeUpdate();
🔎 행은 늘어났지만 Statement를 사용할때 보다는 프로그램이 간결해짐
🔎 SQL 문에서 변수가 와야 할 위치에는 물음표만 적어 두고, 물음표자리에는 setXxx() 메서드로 값을 설정
➡️ Xxx에는 String, Int 와 같이 자료형별로 다르게 들어감
④ Statement의 close()
- 다른 JDBC 리소스와 마찬가지로 Statement 역시 사용하지 않을 때는 닫아 주어여 함
- PreparedStatement도 마찬가지
stmt.close();
pstmt.close();
📌4단계 : SQL 문 전송
· 데이터를 입력, 수정, 삭제하려고 SQL문을 만들때는 PreparedStatement를 사용하여 변수와 적절히 조합하면 됨
➡️ executeUpdate() 메서드를 사용
int count = pstmt.executeUpdate();
💡 이 때 executeUpdate() 메서드는 처리한 로우의 개수를 반환
➡️ 처리된 항목이 없다면 0을 반환
💡 처리 결과는 반환값을 받아서 확인해야 하고, 그럴 필요가없다면 굳이 반환을 받지 않아도 됨
📌 5단계 : 결과받기
· 데이터베이스에서 데이터 결과를 받으려면 Statement나 PreparedStatement의 executeQuery()를 사용
· 입력, 수정, 삭제와 달리 데이터를 가져올 때는 가져온 결과 데이터를 처리하는 ResultSet 객체가 필요
ResultSet rs = pstmt.executeQuery():
💡 ResultSet은 데이터베이스 내부적으로 수행한 SQL 문의 처리 결과를 JDBC에서 쉽게 관리할 수 있게 함
💡 필요한 데이터를 모두 가져온 후 ResultSet을 close()하고나서 connection을 close() 해야 함
💡 ResultSet은 next() 메서드를 사용하여 다음 로우로 이동
➡️ 커서를 최초 데이터의 위치로 이동시키려면 ResultSet을 사용하기 전에 rs.next() 메서드를 한 번 호출
· 대부분은 다음과 같이 executeQuery() 메서드를 수행한 후 while(rs.next())와 같이 더 이상 로우가 없을 때까지 루프를 돌면서 데이터를 처리하는 방법을 사용. 이 때 로우에서 각 컬럼값을 가져오려면 rs.getXxx() 메서드를 사용
ResultSet rs = psmt.executeQuery();
while(rs.next()) {
name = rs.getString(1); // or rs.getString("name");
age = rs.getInt(2); // or rs.getInt("age");
}
rs.close();
🔎 getXxx() 메서드에서 컬럼을 지정하는 방법으로 해당 컬럼의 index 값(1부터 시작) 이나 컬럼 이름을 사용
🔎 가급적 index보다는 컬럼 이름을 사용하는 편이 코드 이해나 유지보수에 더 유리
🔎 ResultSet의 사용이 끝났으면 rs.close() 메서드를 사용하여 ResultSet을 닫아 주어야 함
📌 6단계 : 연결 해제
· 데이터베이스와 연결을 관리하는 Connection 인스턴스는 사용한 후 반납하지 않으면 계속 연결을 유지
· 데이터베이스 연결은 해당 연결을 이용한 작업이 모두 끝나는 시점에서 close() 메서드를 사용하여 해제해야 함
conn.close();
4) 주요 클래스
(1) Statement 주요 메서드
boolean execute(String sql)
👾주어진 SQL문 sql을 실행 - select 구문을 실행하는 경우에는 true를 리턴, 그렇지 않은 경우에는 false 리턴 - true를 리턴하는 경우에는 getResultSet() 메서드를 이용하여 ResultSet 객체를 생성 - update, insert, delete 구문을 사용하는 경우에는 false를 리턴하고, getUpdateCount() 메서드를 이용하여 영향받은 행의 갯수를 알아낼수 있음
ResultSet executeQuery(String sql)
👾select 구문을 실행할 때 사용
int executeUpdate(String sql)
👾select를 제외한 나머지 insert, create, update, delete 구문을 실행할 때 사용 - 이 때 영향을 받은 행의 개수를 리턴
ResultSet getResultSet()
👾현재 SQL 구문을 실행한 결과를 리턴 - select 구문을 실행했을 경우에만 유효
int getUpdateCount()
👾 현재 SQL 구문의 실행으로 영향을 받은 행의 개수를 리턴 - select를 제외한 나머지 구문에서만 유효
(2) ResultSet
👩🏻💻 Statement 객체의 getResultSet(), executeQuery() 메서드가 리턴하는 객체로서 select 구문 실행 결과를 다룰 때 사용
👩🏻💻 select 구문을 실행하여 ResultSet 객체가 생성되면 커서 cursor 가 만들어지고 select 구문 실행 결과를 가르킴
boolean next()
👾커서를 다음 행으로 이동 - ResultSet 객체가 처음 생성된 직후에 next() 메서드를 한 번 호출해야 첫 번째 행을 커서가 가르키게 됨 - 성공적으로 커서가 이동하면 true를 리턴하고 더 이상 없어서 커서를 이동시킬 수 없으면 false를 리턴
boolean previous()
👾커서를 이전 행으로 이동 - 성공적으로 커서가 이동하면 true를 리턴하고 더 이상 결과가 없어서 커서를 이동시킬 수 없으면 false를 리턴
👾colName에 지정된 속성명에 해당하는 실제 데이터를 리턴 - 예를 들어 속성의 데이터 자료형이 String 형과 호환되는 속성이라면 getString() 메서드를 사용 - 속성 이름 대신 속성의 위치 정보를 colIndex로 줄 수 있음 맨 앞의 속성은 '1', 두 번째 속성은 '2'와 같이 숫자로 속성의 위치를 지정
(3) PreparedStatement
👩🏻💻 Statement 객체의 execute계열 메서드는 모두 SQL 문을 컴파일하고 바로 수행시켜서 결과를 리턴
👩🏻💻PreparedStatement 객체는 SQL 문을 미리 컴파일하여 실행하기 직전의 상태로 만든 후 실제 실행은 나중에 필요에 따라 할 수 있음
👩🏻💻같은 SQL 문을 여러 번 실행시켜야 하는 경우에 는 Statement 객체보다 PreparedStatement 객체 사용이 더 효과적
👩🏻💻 PreparedStatement 객체로 생성되는 SQL 문은 마치 함수처럼 매개변수를 설정, 필요에 따라 매개변수의 값을 바꿔 실행가능
➡️ 비슷한 SQL 구문을 반복적으로 실행시켜야 하는 경우에도 유용
➡️ 매개변수를 정의할 때에는 '?' 을 사용하고 매개변수에 값을 설정할때에는 set계열 메서드를 사용
📌DBMS와 Java의 자료형 변환
· DBMS에서의 컬럼의 자료형과 Java 자료형, 그리고 관련된 JDBC 메소드 간의 변환표