• 1. K번째 약수 구하기
# 1. 환경설정 및 K번째 약수 풀이
# 자연수 N, K번째로 작은 수
N, K = map(int, input().split()) 
a = [] # 리스트 생성

# 약수 구하기 : 1부터 N까지 나누었을 때 
for i in range(1, N+1):
    a.append(int(N//i))
    
    
# 약수 중복 제거 
newList = list(set(a))
if len(newList) < K: # 약수 개수가 K보다 작은 경우 -1
    print(-1)
else:
    newList.sort() # 약수 오름차순 정렬
    print(newList[K-1]) # K번쨰 값 출력

 

  • 2. K번째 수
# 2. K번째 수
N,s,e,k = 6,2,5,3
array1 = [5, 2, 7, 3, 8, 9]
newArray1 = array1[s-1:e] # 2 7 3 8 
newArray1.sort() # 오름차순
print(newArray1[k-1]) # K번째 수 출력

 

  • 3. K번째 큰 수
# 3. K 번째 큰 수
N, K = 10, 3 # 자연수 N, K 번째 수
arr = [13,15,34,23,45,65,33,11,26,42]
# arr = list(map(int, input().split()))
res = set() # 중복 제거 set 사용

# 3개씩 뽑아서 더하기
for a in range(N):
    for b in range(a+1, N):
        for c in range(b+1, N):
            res.add(arr[a]+arr[b]+arr[c])
res = list(res)
# 내림차순 정렬
res.sort(reverse=True)
# K 번째 수 구하기
print(res[K-1])

 

  • 4. 대표값
  • 반올림 구하기 round 대신 int(a+0.5) 
# 4. 대표값 - 평균에 가까운 수 구하기
N = 10
arr = [65, 73, 66, 87, 92, 67, 55, 79, 75, 80]
avg = sum(arr)//10
min = float('inf')
resIdx = 0

# enumerate을 사용하면 배열의 idx, val - 인덱스, 값 반환
for idx, val in enumerate(arr):
    dff = round(abs(avg-val))
    if min > dff:
        min = dff
        resIdx = idx
    elif min == dff and arr[resIdx] < val:
        resIdx = idx
print(round(avg), resIdx+1)

# round 반올림 오류
# round_half_even 방식 사용 -> 0.5 인 경우, 0 반환
# round 대신 0.5를 더해주고 int()를 사용
a = 66.5
print(a)
a = a+0.5
print(int(a))

 

  • 5. 정다면체
# 5. 정다면체 - 두개의 정다면체의 값을 더할 때 가장 확률 높은 값 구하기
N, M = 4,6
arr = [0]*(N+M) # 최대값은 N+M

for i in range(1, N+1):
    for j in range(1, M+1):
        # 각 수에 cnt++ 
        arr[i+j-1] = arr[i+j-1] + 1

max = max(arr)

for idx, val in enumerate(arr):
    if max == val:
        print(idx+1, end=' ')

 

  • 6. 자릿수의 합
# 6. 자릿수의 합 - 각 자릿수의 합을 구하고 가장 높은 자연수 출력
N = 3
arr = [125, 15232, 97]
max, maxVal = 0, 0

def digit_sum(x): # 자릿수 구하기 함수
    sum = 0
    while x > 0:
        sum = sum + int(x % 10)
        x = x/10
    return sum

for i in arr: # 자릿수의 최대값 구하기
    tmp = digit_sum(i)
    if max < tmp:
        max = tmp
        maxVal = i
print(maxVal)

 

  • 7. 소수 - 에라토스테네스의 체
  • 소수 개수 구하기
# 7. 소수 - 에라토스테네스의 체
# 소수 개수 구하기
N = 20
arr = [0]*(N+1)
cnt = 0

# 1은 소수가 아니다.
for i in range(2, N+1):
    if arr[i] == 0: # 배열의 값이 0 인 경우 = 소수
        cnt = cnt + 1
        # 소수의 배수는 1로 체크
    for j in range(i, N+1, i):
        arr[j] = 1
print(cnt)

 

  • 8. 뒤집은 소수
# 8. 뒤집은 소수 - 자연수를 뒤집은 값이 소수일 경우 출력
N = 5
arr = [32, 55, 62, 3700, 250]

def reverse_num(num):
    res = 0
    while num > 0:
        tmp = int(num % 10)
        res = res*10+tmp
        num = num//10
    return res

def isPrime(num):
    if num == 1:
        return False
    for x in range(2, num):
        if num % x == 0:
            return False
    return True

for x in arr:
    reverse = reverse_num(x)
    if isPrime(reverse):
        print(reverse, end=' ')

 

 

  • 소수 구하기 알고리즘 - 제곱근 사용
def isPrime(num):
    if num == 1:
        return False
    for x in range(2, int(math.sqrt(num) + 1)):
        if num % x == 0:
            return False
    return True

 

 

  • 9. 주사위 게임 
# 9. 주사위 게임 
# 3개의 주사위를 각 규칙에 맞게 계산하고, 가장 최대값 출력
N = 3
arr = [[3, 3, 6], [2, 2, 2], [6, 2, 5]]
maxRes = 0

for i in range(len(arr)):
    count = 0
    value = 0
    maxCnt = 0
    for j in range(len(arr)):
        if value == arr[i][j]:
            count = count+1
        else:
            maxCnt = max(count, maxCnt)
            count = 1
            value = arr[i][j]
        if j+1 == len(arr):
            maxCnt = max(count, maxCnt)
    if maxCnt == 3: # 규칙 1(같은 눈3개)
        reward = 10000+(value*1000)
    elif maxCnt == 2: # 규칙 2(같은 눈2개)
        reward = 1000+(value*100)
    else: # 규칙 3(같은 눈X)
        reward = max(list(arr[i]))*100
    maxRes = max(maxRes, reward)
print(maxRes)

 

  • 10. 점수 계산
# 10. 점수 계산 - OX 퀴즈 연속답 가산점 계산
N = 10
arr = [1, 0, 1, 1, 1, 0, 0, 1, 1, 0]
subSum = 0
score = 0

for i in arr:
    if i == 0:
        subSum = 0
    else:
        subSum = subSum+1
        score = score + subSum
print(score)

 

JDBC(Java Database Connectivity)

- Java class와 Interface의 집합

- Java 프로그램이 DB에 의존하지 않도록, 공통된 Interface를 제공하는 JDBC 이용


 

JDBC 연결

(1) JDBC driver loading

- 사용하려는 데이터베이스에 맞는 JDBC driver class 등록

- Class라는 class가 존재

- driver Manager class 이용

// 1. JDBC driver Loading
// MySQL 8.0 부터는 아래의 Class 이용
Class.forName("com.mysql.cj.jdbc.Driver");
System.out.println("드라이버 로딩 성공");

 

(2) DBMS와 연결

- 실제로 데이터베이스와 연결된다.

- 성공하면 Connection instance가 생성된다 

- 세션을 통해 생성되는 과정 때문에 부하가 많이 걸린다.

- 자원을 다 사용한 후, 해제 해주어야 한다.(close)

- Database의 Session이 닫힐 수 있도록 쿼리ㅓ 작성

- JDBC URL 

String jdbcURL = "jdbc:mysql://localhost:3306/sqldb?characterEncoding=UTF-8&serverTimezone=UTC&useSSL=false";
con = DriverManager.getConnection(jdbcURL, "user", "password");
System.out.println("데이터 베이스 연결 성공!");

 

(3) Statement 생성

1. 일반 statement

2. preparedStatement : 1번의 개량형

3. callable statement 

- 3번은 stored procedure를 호출할 때 사용한다.

- 1, 2번은 구문으로 실행한다.

String sql = "SELECT userId, name, addr FROM usertbl";
pstmt = con.prepareStatement(sql);

 

 

(4) Query 실행

- statement를 이용해서 SQL query를 DBMS에 전달하고 실행한다.

1. execute() 

2. executeQuery() -> SELECT

3. executeUpdate() -> INSERT, UPDATE, DELETE

- 1번 X, 2, 3번 사용

rs = pstmt.executeQuery();

 

 

(5) 결과쿼리(ResultSet)

- 쿼리문을 실행한 결과 record를 가리키는 포인터

- rs.next()를 통해서 다음 행으로 넘어갈 수 있다. -> 가능하면 true, 불가능하면 false return

- rs는 쿼리를 실행시켜서 현재 데이터베이스에 있는 데이터를 그대로 가져와서 자바 프로그램에 전달해준다. 실시간으로 바뀐 데이터는 전달해주지 않는다.

- scrollable cursor은 연동이 되기 때문에 데이터베이스에 직접 접근해야해서 부하가 많이 걸린다.

ResultSet rs = pstmt.executeQuery();

- rs.getString() : String으로 타입 변환(DB의 데이터타입을 Java의 데이터타입으로 변환)

rs.getString(”name”);  // 홍길동을 java string 형태로 가져온다.
rs.getString(2); // 홍길동
// 5. 결과처리
while(rs.next()){ // rs 쭉 실행하기 -> 위에서부터 밑에까지 쭉 내려가세요
    String id = rs.getString(1);
    String name = rs.getString(2);
    String addr = rs.getString(3);
    System.out.println(id+" "+name+" "+addr);
}

Connection pool

- 동시에 많은 사용자에 대한 데이터베이스 쿼리를 제공하기 위해 사용한다.

- connection을 많은 사용자와 공유하게 되면? -> 트랜젝션 발생

- pooling 기법을 사용해서 해결한다.

 

 

pooling

- 속도 향상(생성과 소멸 과정X -> 반납 대여 과정)

- 자원의 효율성

- connection 수를 제어한다.

- 직접 구현하는 것이 아니라, Apache Commons의 DBCP 사용

 

 

Apache Commons 

- 재사용 가능한 자바 기반의 컴포넌트를 모아놓은 통합 프로젝트

- dbcp : Database connection pooling services

 

  • 입력 하나 받고 출력
n = input() # 입력 하나 받기
print(n) # 출력

 

  • 값 교환
a, b = 10, 20
print(a, b) # 10 20
a, b = b, a
print(a, b) # 20 10

 

  • 변수 타입 출력
a = 10
print(type(a)) # int
int, float, str

 

  • 출력 방식
print("number")
print(a, b, c, sep=', ') # a, b, c 분리하는 방법 sep

 

  • 줄바꿈 안하는 방법(end)
print(a, end=' ')

 

  • 변수 입력과 연산자
a = input() # 입력 방법
print(a)

a = input("숫자를 입력하세요 : ") # 숫자를 입력하세요
a, b = input("숫자를 입력하세요 : ").split()

# 2개를 입력 받는 방식이 아니라, input으로 입력을 받은 후
# split을 통해 2개로 값을 분리 -> split
# split으로 분해되면 문자열로 들어간다.

print(a,b) # 3 5
print(a+b) # 35

# 다른 방법 - map
a, b = map(int, input("숫자를 입력하세요 : ").split())

 

  • 사칙연산
input 3 2
a+b # 5
a-b # 1
a*b # 6
a/b 나누기 # 1.5
a//b 몫 # 1
a%b 나머지 # 2
a**b 거듭제곱 # 3^2

 

  • 조건문
x=7
if x==7:
    print("Lucky")

if x>0 and x<10:
    print("10보다 작은 자연수")

if 0<x<10:
    print("10보다 작은 자연수")

if x>0:
    print("양수")
else:
    print("음수")

if x>=90:
    print('A')
elif x>=80:
    print('B')
else:
    print('F')

 

  • 반복문
a = range(10) # 0~9까지 10개의 수
a = range(1, 11) # 1부터 10(1~10) 
print(list(a))

for i in range(10): # 0~9
    print(i)

for i in range(1,11): # 0~9
    print(i)

for i in range(10, 0, -2) # 10 8 6 4 2
    print(i)

i=1
while i<=10:
    print(i) # 1 ~ 10
    i=i+1 

i = 10
while i>=1:
    print(i)
    i = i-1

i=1
while True: # 1 ~ 10
    print(i)
    if i == 10:
        break
    i=i+1

for i in range(1, 11):
    if i%2==0:
        continue
    print(i) # 1 3 5 7 9

for i in range(1, 11):
    print(i)
    if i>15:
        break
else:
    print(11) # for문 정상 실행시 for else 구문 출력

# N = input() for문에서 N+1이 문자로 인식된다.
N = int(input()) # int 명시해주기
evenSum = 0
totalSum = 0
for i in range(1, N+1): 
    totalSum = totalSum + i
    if(i%2==1): # 짝수 출력
        print(i, end=' ')
    if(N%i==0): # 약수 출력
        print(i, end=' ')
print(totalSum) # 총합 출력

 

 

  • 중첩 반복문(2중 for문)
for i in range(5): # 5번 반복
    print('i:', i, sep='', end=' ')
    for j in range(5):
        print('j:', j, sep='', end=' ')
    print()

for i in range(5):
    for j in range(i+1):
        print('*', end=' ')
    print()

for i in range(5):
    for j in range(5-i):
        print('*', end='')
    print()

 

  • 문자열 접근 방법
# 문자열 접근 방법 1
for i in range(len(msg)): # 1~10
    print(msg[i], end='')

# 문자열 접근 방법 2
for x in msg: 
    print(x, end='')

 

  • 대소문자, 문자열 쪼개기
msg = "It is Time"
print(msg.upper()) # 대문자 변환
print(msg.lower()) # 소문자 변환
print(msg)

tmp = msg.upper()
print(tmp)
print(tmp.find('T')) # 1 인덱스 번호를 찾아준다.
print(tmp[1]) # T
print(tmp.count('T')) # 2 특정 문자의 개수 출력
print(msg[:2]) # It : 제일 처음부터 1, 2번까지 
print(msg[3:5])
print(len(msg)) # 10


# 대소문자 출력
for x in msg:
    if x.isupper(): # 대문자만 출력
        print(x)

msg = "It is Time"
for x in msg:
    if x.isalpha(): # 알파벳만 출력
        print(x, end='')

 

  • ASCII 표현
tmp = 'AZ'
for x in tmp:
    print(ord(x)) # ord는 아스키 넘버 출력 -> 65 90

tmp = 65
print(chr(tmp)) # 아스키 코드 출력 -> A

 

  • 리스트와 내장함수
import random as r
a=[]
b=list()
print(a) # 같은 표현 1
print(b) # 같은 표현 2

a = [1,2,3,4,5]
b=list(range(1, 11)) # 1부터 10까지의 리스트
print(a+b) # 두개의 리스트를 합친다.
a.append(6) # 배열의 뒤에 원소를 추가하는 함수
a.insert(3, 7) # 3번 인덱스에 7 입력
a.insert(3, 7) # 3번 인덱스에 7 입력
a.pop() # 리스트 맨 뒤의 원소를 없애준다
a.insert(3, 7) # 3번 인덱스에 7 입력
a.pop(3) # 3번 인덱스 값을 제거해준다.
a.remove(4) # 4라는 값 찾아서 제거
print(a.index(5)) # 5라는 값의 인덱스 출력

a = list(range(1,11)) # 1부터 10까지의 리스트 생성
print(a) 
print(sum(a)) # 리스트 원소들의 총합
print(max(a)) # 최대값 출력
print(min(a)) # 최소값 출력
print(min(7,5)) # 인자 값들 중에서 최소값을 찾아주는 min

import random as r 
r.shuffle(a) # 랜덤으로 값을 섞어주는 라이브러리 
a.sort() # 오름차순 정렬
a.sort(reverse=True) # 내림차순 정렬
a.clear() # 리스트의 모든 값들이 삭제된다.

a = [23, 12, 36, 53, 19]
print(a[:3]) # 0~2번 index value output
print(a[1:4]) # 1~3번 index
print(len(a)) # 5

 

 

  • 반복문으로 리스트 원소 접근
for i in range(len(a)): # 같은 결과 1
    print(a[i], end=' ')
print()

for x in a: # 같은 결과 2
    print(x, end=' ')
    
    
a = [23, 12, 36, 53, 19]
# 방식1
for x in enumerate(a): # 튜플 자료구조
    print(x)

# 방식2
for x in enumerate(a):
    print(x[0], x[1])
    
# 방식3 을 제일 많이 사용한다.
for index, value in enumerate(a):
    print(index, value)
    
# 출력 결과
# (0, 23)
# (1, 12)
# (2, 36)
# (3, 53)
# (4, 19)

 

 

리스트, 튜플, 셋, 딕셔너리

  • list : [], 값 변경 가능
  • tuple : (), 값 변경 불가능
  • set : {}
  • dictionary : {key:value, key:value}
b = (1,2,3,4,5)
print(b[0]) # 접근 방법 -> 1 출력
b[0] = 7 # 튜플의 값은 변경이 불가능하다

# if all, if any 사용방법
if all(50>x for x in a):
    print("YES")
else:
    print("NO")
# for문으로 a 리스트를 변수 x로 접근
# 60보다 큰 값들이 없어요 
# if all은 모든 값들이 해당되어야 한다. 1개라도 거짓이면 X

if any(15>x for x in a):
    print("YES")
else: 
    print("NO")
# any는 하나라도 참이면 참을 반환한다.

 

MySQL Data Type

- 빈번한 데이터 변화에는 VAR(variable)보다 CHAR 사용 권장

 

MySQL 내장 함수

- 문자열 함수

(1) CHAR_LENGTH : 문자 수 계산

(2) LENGTH : 문자 byte 계산, 한글은 1글자에 3byte

(3) CONCAT : 문자열 연결

(4) CONCAT_WS : 문자열에 특정 문자 넣기

(5) FORMAT : 3자리씩 콤마를 찍어준다. -> 금액 표현

(6) TRIM : 문자열 앞 뒤 공백 제거

(7) REPLACE : 특정 문자열을 다른 문자열로 교체

(8) SUBSTRING : 지정 범위 문자열 출력

 

- 날짜 함수

(1) CURDATE() : 현재 연월일, YEAR(CURDATE()) 으로 연도만 사용할 수 있다.

(2) NOW() : 현재 연월일 및 시분초

SELECT CHAR_LENGTH('abcde'), -- 5 --
	CHAR_LENGTH('홍길동'), -- 3, 문자 수 계산 --
    LENGTH('abcde'), -- 5, byte 수 계산 --
    LENGTH('홍길동'); -- 9 --


SELECT CONCAT('소리없는', '아우성'), -- 문자열 연결 --
CONCAT_WS('-','2022','02','20'); -- 문자열에 끼워넣기 --

SELECT FORMAT(1234567.1415234,3); 
-- 소수점 3째자리,--


SELECT TRIM('		소리없는 아우성	'),
	REPLACE('이것은 소리없는 아우성','소리', '양심'),
    SUBSTRING('이것은 소리없는 아우성',3,5);

SELECT CURDATE(),
	NOW(),
	YEAR(CURDATE());

 

 

 

 

 

 

SQL

- DML(Data Manipulation Language) : Insert, select, update, delete

- DDL(Data Defination Language) : Create, Drop, Alter

- DCL(Data Control Language) : grant, deny

 

DML vs DDL

- Transaction의 사용 가능 유무

- DML Transaction 영향 O

- DDL Transaction 영향 X

 

Transaction(트랜잭션)

- 작업의 최소 단위

- 임의로 설정할 수 있는 개념이다.

- 여러 SQL 문장을 하나의 논리적인 단위인 Transaction으로 설정한다.

- 사용 이유 : Transaction 설정시 DBMS가 ACID 보장

- commit(반영) or rollback(무효화)

 

MySQL Workbench Auto Commit Transactions

- 워크벤치 기능에 쿼리를 할 때마다 자동적으로 트랜잭션해주는 모드가 켜져 있다.


ACID

(1) Atomicity(원자성)

- All or nothing

- 모든 작업이 완료되거나 실행이 아무것도 되지 않아야 한다.

 

(2) Consistency(일관성)
- 트랜잭션이 끝난 후, 결과가 제약조건에 위배 되지 않는 상태(correct state)이 된다.

 

(3) Isolation(독립성)

- 모든 트랜잭션이 다른 트랜잭션에 독립적이다.

- Thread 동기화 처리와 일치한다.

 

(4) Durability(지속성)

- 트랜잭션 종료 시, 해당 결과가 2차 저장소에 영구적으로 저장된다.

 

Ex. 이체 시스템

- A 계좌 SELECT (잔고 확인)

- A 계좌 UPDATE (잔고 수정)

- B 계좌 SELECT (입금 전 금액) 

- B 계좌 UPDATE (입금 후 금액)

 


 

JOIN

(1) INNER JOIN

- 일반적인 JOIN

 

(2) OUTER JOIN

- LEFT, RIGHT, FULL

- JOIN 조건을 만족하지 않는 행을 포함한다.


(3) SELFT JOIN

 

(4) CROSS JOIN

- 일반적으로 많이 사용하지 않는다.

- 더미데이터 생성에 사용

 


실습 SQL문 정리

-- 평균 구하기 --
SELECT AVG(칼럼명) FROM 테이블명;

-- 사용자별 평균 구매 금액 --
SELECT userID, AVG(칼럼명) FROM 테이블명
GROUP BY userID;

-- 가장 큰 키, 작은 키 회원의 이름과 키 출력 --
SELECT 이름, 키 FROM 테이블명
WHERE 키 = (
SELECT MAX(키 칼럼) FROM 테이블명
)
OR 키 = 
(
SELECT MIN(키 칼럼) FROM 테이블명
);

-- 사용자별 총 구매 금액 1000 이상 --
SELECT userID, SUM(구매금액*구매횟수) 
FROM 테이블명
GROUP BY userID
HAVING SUM(구매금액*횟수) >= 1000;


-- 트랜잭션 --
SELECT distinct userID FROM 테이블명;

START TRANSACTION -- 트랜젝션의 시작 구문 -- 

DELETE FROM 테이블명; -- 테이블 삭제 --
DELETE FROM 테이블명 WHERE 칼럼명 = '조건' LIMIT 100; -- 상위 100개만 지우기 --

COMMIT; -- 지금 작업한 내용 데이터베이스에 적용 -- 
ROLLBACK; -- 무효화 --

연습문제 SQL문 정리

-- FLOOR(AVG(SAL)) : 정수만 출력, 실수 값 버리기 --
SELECT JOB as '직무', FLOOR(AVG(SAL)) as '급여 평균' FROM EMP
WHERE DEPTNO=30
GROUP BY JOB;


-- 칼럼들의 누적 합계 구하기 -- 
-- FORMAT(금액, '0.000') : 금액 천단위마다 콤마 출력 --
SELECT JOB as '직무명', FORMAT(SUM(SAL), '0,000') as '급여의 합' FROM EMP
GROUP BY JOB
UNION ALL
SELECT 'TOTAL', FORMAT(SUM(SAL), '0,000') FROM EMP
ORDER BY '직무명';


-- CROSS JOIN : 2개 테이블 열 기준으로 붙이기 --
SELECT * FROM A CROSS JOIN B;


-- 1. IFNULL(칼럼명, 0) : NULL 처리 (NULL + 0이상의 값 = NULL이 출력된다) --
-- 2. FORMAT()으로 금액 천단위마다 콤마 + CONCAT()으로 금액 + '원' 출력
SELECT ENAME as '직원명', CONCAT(FORMAT(SAL+IFNULL(COMM, 0), '0,000'),'원') as '급여' FROM EMP
ORDER BY SAL+IFNULL(COMM, 0) DESC;


-- DATE_FROMAT() : DATE 타입 출력 형식 -- 
-- CASE WHEN ~ THEN : 조건별 표현식 --
SELECT ENAME as '직원명', DATE_FORMAT(HIREDATE, '%Y년 %m월 %d일') as '입사년월일',
   (CASE 
 	WHEN HIREDATE BETWEEN '1980-01-01' AND '1980-12-31' THEN 'A'
        WHEN HIREDATE BETWEEN '1981-01-01' AND '1981-12-31' THEN 'B'
        WHEN HIREDATE BETWEEN '1982-01-01' AND '1982-12-31' THEN 'C' 
        WHEN HIREDATE BETWEEN '1983-01-01' AND '1983-12-31' THEN 'D'
    END) as '등급'
 FROM EMP;
 
 
 -- 3중 조인 --
SELECT * FROM A
INNER JOIN B
ON A.칼럼1 = B.칼럼1
INNER JOIN C
ON B.칼럼2 = C.칼럼2;

 

 

Database(데이터베이스)

- 데이터의 집합

- 관련있는 대용량의 데이터 집합들을 체계적으로 구현해 놓은 것

- 여러명 사용 가능, 데이터 처리, 여러 개의 Database 관리 가능

- DBMS(Database Management System) : 데이터베이스를 운영, 관리 하는 Software

 

 

MySQL Oracle, 무료, 유료
MariaDB MariaDB, 무료
Oracle Oracle, 상용 시장 점유율 1위
DB2 IBM, 메인 프레임 시장 점유율 1위
SQL Server Microsoft, 중/대형급 시장 사용
PostgreSQL PostgreSQL, 무료

 

DBMS(Database Management System) 특징

(1) 무결성 : 데이터의 오류 X, constraints(제약 조건)

(2) 독립성 : DB 물리적 크기, 위치 변경에도 SW에 영향을 끼치지 않는다.

(3) 보안성 : 계정관리, 권한 설정

(4) 중복 최소화 : 자료 중복, 데이터 종속성 해결

(5) 안정성 (backup/resotre) 

 

 

DBMS의 종류

(1) 계층형 DBMS : 각 계층은 tree 형태, 변경이 어렵다는 단점

(2) 네트워크 DBMS : 계층형의 단점을 보완, 모든 구조를 이해해야 하기 때문에 구현이 어렵다.

(3) 관계형 DBMS : 테이블(table)이라는 최소 단위로 구성. 

- 테이블 : 열(column) + 행(row)

 

(4) 객체지향 Database

(5) 객체-관계형 Database : 대표 Oracle. 관계형 데이터베이스에서 객체지향의 장점을 추가한 데이터베이스

- 사용자 타입 지원

- 참조 타입 지원 : 레코드가 다른 레코드 참조 가능

- 중첩 테이블 지원 : row가 다른 테이블로 구성

- 객체 간의 상속 가능

 

 


DBMS 구조

- Table : 데이터를 저장하기 위한 "표" 형태의 구조(relation)

- PK : 각각의 row를 unique하게 식별할 수 있는 column의 집합

 

Schema(스키마)

- database 안에서 (data의 구조, 표현 방법, 타입, 관계) 형식 언어를 이용해서 정의한 구조

- MySQL(MariaDB)에서는 schema = Database

(1) 외부 스키마 external schema : 사용자 입장에서 데이터베이스 모습으로 조직의 일부분 정의

(2) 개념 스키마 conceptual schema : 데이터를 통합한 조직 전체의 데이터베이스 구조를 논리적으로 정의 -> data의 논리적 구조

(3) 내부 스키마 Internal schema : 전체 데이터베이스의 물리적 저장 형태 기술

 

 

스키마 생성 실습

- schema : shopdb

- table 2개 생성

1. memberTBL

열 이름(한글) 영문 이름 데이터 형식 길이 NULL 허용
아이디 memberID 문자(CHAR) 8글자(영문) X
회원 이름 memberName 문자(CHAR) 5글자(한글) X
주소 memberAddress 문자(CHAR) 20글자(한글) O

 

2. productTBL

열 이름(한글) 영문 이름 데이터 형식 길이 NULL 허용
제품 이름 productName 문자(CHAR) 4글자 (한글) X
가격 cost 숫자(INT) 정수 X
제조일자 makeDate 날짜(DATE) 날짜형 O
제조회사 company 문자(CHAR) 5글자(한글) O
남은 수량 amount 숫자(INT) 정수 X

 


Index

- primary key를 설정하려면, 해당 column index가 설정

 

 

view

- 가상의 테이블

(1) 안전하게 데이터 유지

(2) 보안적인 측면

(3) 사용의 편리성

 

 

Procedure(프로시저)

- 쿼리를 마치 하나의 함수처럼 실행하기 위한 쿼리의 집합

- 여러줄의 쿼리문을 한 번의 요청으로 실행할 수 있도록 해준다.

- 장점 : 최적화, 캐시, 유지 보수, 트래픽 감소, 보안

- 단점 : 호환성, 성능, 디버깅

 

 

Stored Procedure(저장 프로시저)

- 함수 Interface 제공

 

 

Trigger

- 테이블에 부착

- Insert, Update, Delete가 발생한다.

- 테이블에서 회원정보를 삭제해야 하는 경우 -> 일반적으로 flag(update)

 


MySQL workbench utility

(1) SQL 구문 자동 생성

(2) Query editor 설정

- 예약어 대문자로 변경

- 자동완성

- 주석쿼리

- SQL 구문의 표준 형태로 변경

(3) 사용자 생성과 권한

 


SQL : SELECT 구문

SELECT 

FROM

WHERE 조건

GROUP BY 

HAVING 조건

ORDER BY

Thread 

- 생성

- start()

- sleep()

- stop() 사용 금지 -> 직접 구현 권장 : stop() 스레드 종료 , suspend() 스레드 일시 정지, resume() 일시중지 스레드 재시작

- interrupt() : interrupted(), isInterrupted()

- yield() : 스레드가 자신에게 주어진 실행시간을 모두 쓰지 않고, 다른 스레드에게 양보한다. -> 응답성을 높이기 위해 사용

 


sleep() Method 

- sleep(long millisecond) : 일정 시간동안 Thread를 중지 시킨다.

- 지정된 시간 후 자동으로 실행 대기 상태가 된다.

- 일시 정지 상태에서 Interrupt() 호출 시, InterruptException이 발생하면서 깨어난다.

- static method

 

 

join() Method

- 스레드는 각자 독립적으로 실행되지만, 다른 스레드가 종료된 이후 실행해야하는 경우가 있다.

- 실행 대기 상태로 가기 위해서는 join() 메소드를 멤버로 가지는 스레드가 종료되거나, 매가 값으로 주어진 시간이 지나야 한다.

- join()에 인자를 주지 않는 경우, 호출하는 스레드가 무한히 기다리는 상황이 생길 수 있다. -> ex. thread.join(100);

- insatnce method

 

상태 전이도 - sleep()

 

상태 전이도 - yield()

- 우선순위가 동일한 다른 스레드에게 실행을 양보해주고 실행 대기 상태로 이동

- 프로그램의 응답성을 높여준다.

 

상태 전이도 - join()


interrupt() Method

- stop() : 스레드 강제 중지, 편하지만 deprecated(사용금지)

- strat() : 스레드 시작

 

 

Thread 실행 후, 작업이 끝나기 전에 해당 Thread를 중지 시키고 싶은 경우

- interrupt() 이용

- 직접 중지 시키지 않고, 스레드의 내부 상태(Interrupted state)를 변경 시켜준다.

 

 

Thread Interrupt Method

1. interrupted() // static : 현재 실행중인 스레드가 Interrupt가 걸렸는지 알려준다.

- 상태 값 조사 후, false로 값 변경

- 2번과 다르게 값 변경이 이뤄지기 때문에 주의해서 사용해준다.

 

2. isInterrupted() // non static : 특정 스레드가 Interrupt가 잡혔는지 알려준다. 

- 현재 상태 값만 return true or false

 

 

스레드를 만드는 방법 2가지

1. Thread Class로 직접 생성, runnable interface 사용

- Runnable : 작업 스레드가 실행할 수 있는 코드를 가지고 있는 객체

- Runnable은 Interface Type -> 구현 객체 필요

- Runnable 내부에 있는 run() 메소드를 구현 클래스에서 run()을 Override를 통해 작업 스레드가 실행할 코드를 작성해야 한다.

- Runnable r = new 구현 객체 생성 후, new Thread(r) 구현 객체를 Thread 생성자의 매개 값으로 넣어주면 작업 스레드가 생성

- 생성된 스레드는 바로 실행되지 않고, thread.start()와 같이 start 메소드를 호출해야 실행된다.

- instance를 만들어서 객체를 Thread Class의 인자로 넣어준다.

 

 

2. Thread 하위 클래스로부터 생성

- Thread 하위 클래스로 작업 스레드를 정의하면서 작업 내용 포함

- Thread Class 상속 후, run()을 Override를 통해 작업 스레드가 실행할 코드를 작성한다.

- 생성된 객체에서 start() 메소드를 호출 -> run() 메소드 실행

- IS-A Relationship

- Java(단일 상속 지원)는 다중 상속 X -> Thread Class를 extends할 경우 제약이 생길 수 있다.

- Tightly Coupled 문제가 생길 수 있다.

- Main class가 실행 되면서, 메인 스레드가 생성

- Thread 객체를 생성하고, start() 메소드로 호출하면, 내부적으로 Thread stack을 할당받고, run() 호출


Thread의 이름 

- 메인 스레드 : main

- 직접 생성한 스레드 : Thread-n // n은 스레드의 번호

- setName(), getName()

- Thread.currentThread() : 객체의 참조가 없는 경우 사용

 

 

Thread 상태 전이도

 

+ Recent posts