# https://coding-factory.tistory.com/ 에서 그림 인용
Day 1
1. 입력스트립(Input Stream) & 출력 스트림(Output Stream)
- 자바 데이터는 스트림(Stream) 통해 입출력.
-스트림 ; 단일방향으로 연속적으로 흘러가는 것
=> 순서대로 읽고, 순서대로 내보냄 / byte 단위로 전송
-프로그램 기준 데이터가 들어오면 입력 스트림 , 데이터가 나가면 출력 스트림
-Java.io 패키지 : 파일 시스템의 정보를 얻기 위한 file 클래스와 데이터 입출력하기 위한 다양한 입출력 스트림 클래스 제공
Java.io 패키지의 주요 클래스 |
설명 |
File |
파일 시스템의 파일 정보를 얻기 위한 클래스 |
Console |
콘솔로부터 문자를 입출력하기 위한 클래스 |
InputStream / OutputStream |
바이트 단위 입출력을 위한 최상위 입출력 스트림 클래스 |
FileInputStream / FileOuputStream |
바이트 단위 입출력을 위한 하위 스트림 클래스 |
DataInputStream / DataOutputStream |
|
ObjectInputStream / ObjectOutputStream |
|
PrintStream |
|
BufferedInputStream / BufferedOutputStream |
|
Reader / Writer |
문자 단위 입출력을 위한 최상위 입출력 스트림 클래스 |
FileReader / FileWriter |
문자 단위 입출력을 위한 하위 스트림 클래스 |
InputStreamReader / OutputStreamWriter |
|
PrintWriter |
|
BufferedReader / BufferedWriter
|
- 바이트 단위 입출력 스트림 : 그림, 멀티미디어, 문자 등 모든 종류의 데이터들 주고 받음
- 문자 단위 입출력 스트림 : 오로지 문자만 주고 받을 수 있게 함
-inputStream : 바이트 기반 입력 스트림의 최상위 클래스(추상 클래스)
- 모든 바이트 기반 입력 스트림은 이 클래스를 상속받아 만들어짐
- FileInputStream
- BufferedInputStream
- DataInputStream
메서드 |
설명 |
read() |
입력 스트림으로부터 1바이트를 읽고 읽은 바이트를 리턴합니다. |
read(byte[ ] b) |
입력 스트림으로부터 읽은 바이트들을 매개값으로 주어진 바이트 배열b에 저장하고 실제로 읽은 바이트 수를 리턴합니다. |
read(byte[] b, int off, int len) |
입력 스트림으로부터 len개의 바이트만큼 읽고 매개값으로 주어진 바이트 배열 b[off]부터 len개까지 저장합니다. 그리고 실제로 읽은 바이트 수인 len개를 리턴합니다. 만약 len개를 모두 읽지 못하면 실제로 읽은 바이트 수를 리턴합니다. |
close() |
사용한 시스템 자원을 반납하고 입력스트림을 닫습니다.
|
-OutputStream : 바이트 기반 출력 스트림의 최상위 클래스(추상 클래스) / 모든 바이트 기반 출력 스트림 클래스는 이 클래스를 상속받아 만들어짐
- FileOutputStream : 파일에 저장하는 방법 제공
- PrintStream
- BufferedOutputStream
- DataOutputStream
메서드 |
설명 |
write(int b) |
출력 스트림으로부터 1바이트를 보냅니다.(b의 끝 1바이트) |
write(byte[ ] b) |
출력 스트림으로부터 주어진 바이트 배열 b의 모든 바이트를 보냅니다. |
write(byte[ ] b, int off, int len) |
출력 스트림으로 주어진 바이트 배열 b[off]부터 len개까지의 바이트를 보냅니다. |
flush() |
버퍼에 잔류하는 모든 바이트를 출력합니다. |
close() |
사용한 시스템 자원을 반납하고 출력 스트림을 닫습니다. |
package Lecture.Week2;
import java.io.*;
public class Test04 {
public static void main(String[] args) throws IOException {
InputStream in = new FileInputStream("a.dat" );
OutputStream out = new FileOutputStream("b.dat");
//복사 : dir *.dat 로 확인하고 type b.dat로 확인하고..
// while(true){
// int r = in.read();
// if(r == -1){//더이상 읽을 것이 없을 때
// break;
// }
// out.write(r);
// }
// out.close();
// in.close();
//엄청 많이 씀 -> 외우세용
int r = 0;
byte[] buf= new byte[1024*8];
while(( r = in.read(buf)) != -1 ){// 더 읽을게 남아있다.
out.write(buf, 0, r);
}
out.close();
in.close();
}
}
이를 데코레이터 패턴으로 이해하면
-> out 이 가리키는 대상은
FileOutputStream("d.dat")에 저장하되
ObjectOutputStream 에서 제공하는 방법을 사용하게 된다.
ObjectOutputStream 은 writeInt writeDouble writeUTF 등을 제공
-> 전송 시에 안깨진다.
* ObjectOutputStream 은 writeInt WriteDouble writeUTF 등을 제공 -> 전송
*OutputStream InputStream : 전송단위 byte
* Reader Writer : 전송단위 char : 문자로 된 데이터 전송용
* char : 2바이트 , 유니코드 지원
* 유니코드 : 모든 글자를 다 포용하지 못한다
* -웬만한 건 글자는 포용한다 , 한글 영문 중국어 아랍어 일본어
* 확장 가능한 가변 길이를 가지는 문자체제 도입 UTF - 8.
*OutputStreamWriter InputStreamReader 는 char 입출력을 byte 입출력으로 전환해 줍니다
* 2byte -> 1byte로 바꿔줌*
2. 자바 네트워크에 대한 이해
- 네트워크란?
- 다른 장치로 데이터를 이동시킬 수 있는 컴퓨터들 , 주변 장치들의 집합
- 네트워크의 연결된 모든 장치들을 노드라고 한다
- 복잡한 레이어의 대표적인 모델이 OSI 7계층
- TCP / IP 모델 사용
- IP 주소
- 모든 호스트는 인터넷 주소(Host, IP 주소) 라 불리는 유일한 32비트 숫자로 구성된 주소 체계 이용
- 32비트의 주소 체계를 IPv4 주소라고한다 -> 극복 IPv6
- IP주소를 도메인이름으로 바꾸어 주는 시스템 : DNS
- 포트 & 프로토콜
- 포트
- 물리적 포트
- 논리적 포트
- 프로토콜
- 클라이언트와 서버간의 통신 규약
- TCP / UDP
- 포트
- TCP / UDP
- TCP / IP계층 모델은 4계층 구조(애플리케이션, 전송, 네트워크, 데이터 링크 계층)
- 전송 계층에서 사용하는 프로토콜 TCP / UDP
- TCP (transmission Control Protocol) : 신뢰할 수 있는 프로토콜 / 데이터 상대 측까지 제대로 전달되었는지 확인 메시지를 주고 받음으로써 데이터의 송수신 상태를 점검
- UDP(user datagram protocol) : 신뢰할 수 없는 프로토콜 / 데이터 보내기만 하고 제대로 전달되었는지 확인 하지 않음
3. TCP 통신 / Socket 프로그래밍
- TCP 통신 방식 : 소켓 프로그래밍의 하나 / 스트림 통신 프로토콜 / 양쪽 소켓이 연결 상태여야만 가능 -> 연결 지향 프로토콜
- 수신, 송신 측이 미리 연결 맺고 연결된 순서대로 데이터 교환해야함
- Java.net 패키지에 관련 클래스들 미리 준비 해놓음
- 소켓?
- 네트워크 끝 부분 / 실제 데이터가 어떻게 전송되는 지 상관하지 않고 read/write 인터페이스 제공
- 네트워크 계층과 전송 계층이 캡슐화
- TCP / IP 계층의 TCP를 지원하기 위해 Socket, ServerSocket 클래스 제공
- 클라이언트 : socket 객체 생성, tcp 서버와 연결 시도
- 서버 : SocketServer 객체 생성 , TCP 연결을 청취하여 클라이언트와 서버 연결
- 소켓 스트림
- TCP 소켓은 java.net.Socket 클래스 의미
- Socket 클래스 생성자
- 예외 처리 2개
- 호스트를 찾을 수 없거나, 서버의 포트가 열려있지 않는 경우 (UnknownHostException 예외) 발생
- 네트워크 실패, 방화벽 때문에 서버 접근 할 수 없을 때 (IOException 예외) 발생
- 예외 처리 2개
- Socket 클래스 생성자
생성자 | 설명 |
Socket(Inet(Address address, int port) | InetAdderss 객체와 port 이용하여 socket 객체를 생성한다 |
Socket(String host, int port) | host, port를 이용하여 socket객체를 생성한다. |
- Socket 클래스의 주요 메서드
반환형 | 메서드 | 설명 |
void | close() | 소켓 객체를 닫는다 |
InetAddress | getInetAddress() | 소켓 객체를 InetAddress 객체로 반환한다 |
InputStream | getInputStream() | 소켓 객체로부터 입력할 수 있는 InputStream 객체를 반환한다 |
InetAddress | getLocalAddress() | 소켓 객체의 로컬 주소를 반환한다. |
int | getPort() | 소켓 객체의 포트를 반환한다 |
boolean | isClosed() | 소켓 닫혀있으면 true, 아니면 false 반환 |
isConnected() | 소켓 객체가 연결되어 있으면 true, 연결되어 있지 않으면 false를 반환 | |
void | setSoTimeout(int timeout) | 소켓 객체의 시간을 밀리 세컨드로 설정 |
- 소켓 이용한 입출력 스트림 생성
- 두 개의 네트워크 사이에서 바이트 스트림 통신 제공
- 바이트를 읽기 위한 메서드와 쓰기 위한 메서드 제공
- 두 가지 메서드를 이용하여 클라이언트와 서버간에 통신할 수 있다.
java.io.InputStream getInputStream() throws IOException;
java.io.OutputStream getOutputStream() throws IOException;
Socket socket = new Socket(“211.238.132.50”,4000);
InputStream in = socket.getIputStream();
OutputStream os = socket.getOutputStream();
- 소켓 정보 : 로컬 ip주소와 포트를 알 수 있는 메서드와 socket 으로 연결된 호스트의 ip 주소와 포트를 알 수 있는 메서드 제공
- TCP Server Socket
- 클라이언트의 TCP 연결을 받기 위해서 java.net.ServerSocket 클래스의 객체를 생성
- ServerSocket 클래슨느 네트워크 통신을 수행하기 위해 자신을 바로 사용 X
-> 클라이언트의 TCP 요청에 대한 Socket 객체를 생성하는것 - accept() 메서드 : 클라이언트의 TCP 요청 있을 때 까지 블로킹되는 메서드
- 클라이언트 TCP 요청 -> ACCEPT 메서드-> TCP 소켓 반환
- 일반적으로 accept() 메서드는 무한루프 처리하게 됨
- ServerSocket 클래스의 생성자
- 기존의 tcp 포트 번호가 사용중이라면 IOException 발생
생성자 | 설명 |
ServerSocket(int port) | port 이용하여 ServerSocket 객체 생성 |
- ServerSocket 클래스 주요 메서드
- accept() 가 제일 중요
반환형 | 메서드 | 설명 |
Socket | accept() | 클라이언트의 소켓 객체가 생성되면 서버가 클라이언트와 통신할 수 있는 소켓 객체를 반환 |
void | close() | 서버소켓 객체 닫음 |
int | getLocalPort() | 서버소켓 객체가 청취하고 있는 포트번호 반환 |
getSoTimeout() | 서버소켓 클래스의 accept() 메서드가 유효할 수 있는 밀리 세컨드로 반환 | |
boolean | isClosed() | 서버 소켓 객체의 닫힌 상태를 반환 |
void | setSoTimeout(int timeout) | 서버 소켓 클래스의 accept() 메서드가 유효할 수 있는 시간을 밀리 세컨드로 설정 |
package Lecture.Week2;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
//서버
/*대기 하는 쪽 : 서버
* 찾아 가는 쪽 : 클라이언트
* 먼저 서버가 구동한다. => 포트번호로 묶고 구동해야한다.(1123)
* accept : 대기하다가 클라이언트가 찾아오면 소켓을 생성해서 리턴
* 클라이언트가 찾아가기 위해 ?ip, port번호
* 잘 찾아가면 소켓 생성
* 속 성공 시 두 소켓은 전혀 다른 것이지만 서로 통신할 수 있게 된다. */
public class Test06S {
public static void main(String[] args) throws Exception{
ServerSocket svr = new ServerSocket(1123);
System.out.println("before accept");
Socket skt = svr.accept();
System.out.println("after accept");
InputStream in = new FileInputStream("a.txt");
OutputStream out = skt.getOutputStream();
int r = 0;
while(( r = in.read()) != -1 ) {
out.write(r);
out.flush();//소켓으로 넘어가야함
}
out.close();
in.close();
System.out.println(r);
out = new FileOutputStream("copy.txt");
in = skt.getInputStream();
r = 0;
while((r = in.read())!= -1){
out.write(r);
}
skt.close();
svr.close();
}
}
4. 예외 처리 (try - catch) : 사용자의 잘못된 조작, 개발자의 잘못된 코딩으로 인해 발생하는 프로그램 오류
예외 구문 |
이유 |
ArithmeticException |
정수를 0으로 나눌경우 발생 |
ArrayIndexOutOfBoundsExcetion |
배열의 범위를 벗어난 index를 접근할 시 발생 |
ClassCastExcetion |
변환할 수 없는 타입으로 객체를 반환 시 발생 |
NullPointException |
존재하지 않는 레퍼런스를 참조할때 발생 |
IllegalArgumentException |
잘못된 인자를 전달 할 때 발생 |
IOException |
입출력 동작 실패 또는 인터럽트 시 발생 |
OutOfMemoryException |
메모리가 부족한 경우 발생 |
NumberFormatException |
문자열이 나타내는 숫자와 일치하지 않는 타입의 숫자로 변환시 발생 |
- 예외 처리 코드
try{
//에러가 발생할 수 있는 코드
throw new Exception(); //강제 에러 출력
}catch (Exception e){
//에러시 수행
e.printStackTrace(); //오류 출력(방법은 여러가지)
throw e; //최상위 클래스가 아니라면 무조건 던져주자
}finally{
//무조건 수행
}
문제
1. 점수 관리 프로그램
package HW7_프로그램만들기;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Scanner;
class Score {
int Student_num;
int score;
Score(int Student_num, int score) {
this.Student_num = Student_num;
this.score = score;
}
}
public class Test087 {
static LinkedList<Score> l2 = null;
static int Student_num = 0;
static int score = 0;
static Scanner scan;
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
scan = new Scanner(System.in);
String l = null;
while (true) {
System.out.println("[ M E N U ]");
System.out.println("1. 새 자료");
System.out.println("2. 자료 입력");
System.out.println("3. 파일로 저장");
System.out.println("4. 파일에서 불러오기");
System.out.print("> ");
l = br.readLine();
if (l.equals("1")) {
l2 = new LinkedList<Score>();
System.out.println("# 새롭게 리스트를 만들거나 초기화하였습니다.");
} else if (l.equals("2")) {
if (l2 == null) {
System.out.println("# 리스트 인스턴스가 없습니다. 1번을 선택하여 생성해주세요.");
} else {
System.out.print("학번 : ");
Student_num = scan.nextInt();
System.out.print("점수 : ");
score = scan.nextInt();
l2.add(new Score(Student_num, score));
System.out.println("# 리스트에 학번이 " + Student_num + "인 학생의 점수를 추가했습니다.");
}
} else if (l.equals("3")) {
BufferedWriter bw = new BufferedWriter(new FileWriter("scores.txt"));
for (int i = 0; i < l2.size(); i++) {
bw.write((i + 1) + "번 째 학생 정보");
bw.newLine();
bw.write("Student_num: " + l2.get(i).Student_num);
bw.newLine();
bw.write("score: " + l2.get(i).score);
bw.newLine();
System.out.println("# 성적리스트를 파일로 저장하였습니다.");
}
bw.close();
} else if (l.equals("4")) {
l2 = new LinkedList<Score>();
BufferedReader br2 = new BufferedReader(new FileReader("scores.txt"));
String str = null;
int r = 0;
boolean flag = false;
String[] s = null;
int s_num = 0;
int sc = 0;
while ((str = br2.readLine()) != null) {
if (r % 3 == 1) {
s = str.split(": ");
s_num = Integer.parseInt(s[1]);
flag = true;
r++;
continue;
}
if (flag) {
flag = false;
s = str.split(": ");
sc = Integer.parseInt(s[1]);
l2.add(new Score(s_num, sc));
}
r++;
}
System.out.println("# 저장파일을 불러왔습니다.");
} else if (l.equals("quit")) {
System.out.println("# 프로그램을 종료합니다.");
break;
}
if (l.equals("quit"))
break;
}
br.close();
}
}
2. mp3파일 소켓 저장
<Client>
package Task.Week2;
import java.io.*;
import java.net.Socket;
/*1. 서버에 접속할 소켓생성 CCC
2. 서버의 InputStream을 받아오기
- 서버의 data를 1 byte씩 받아 온다. (InputStream)
3. 저장할 파일에 연결
4. InputStream을 통해 받아온 data를 1 byte씩파일에 작성
- Data가 글자가 아닌 byte이므로 1 byte씩 저장 (FileOutputStream)
5. 연결 해제
*/
public class Client {
public static void main(String[] args) {
try(
Socket skt = new Socket("127.0.0.1", 1123);
ObjectOutputStream oos = new ObjectOutputStream(skt.getOutputStream());
InputStream is = skt.getInputStream();
ObjectInputStream ois = new ObjectInputStream(is);
){
oos.writeUTF("music.mp3");
oos.flush();
int status = ois.readInt();
System.out.println(status);
if(status == 200){
System.out.println("파일 받기");
OutputStream file = new BufferedOutputStream(new FileOutputStream("music2.mp3"));
int r = 0;
while((r = is.read()) != -1){
System.out.println("파일 수신 준비");
file.write(r);
}
}else{
}
;
}catch (Exception e){
e.printStackTrace();
}
}
}
<Server>
package Task.Week2;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
/*Server writeread SSSS
objectinput
1. 클라이언트에서의 접속을 받아 소켓을 생성해줄 서버소켓 생성
2. 클라이언트의 요청에 의해 소켓 생성
3. 클라이언트의 OutputStream을 받아오기
4. 음악파일에 연결
5. 음악파일을 1 byte씩 읽어 (readInt )클라이언트에 전송
- 음악파일에서 1 byte씩 가져왔으므로 Client에도 1 byte씩 보내주어야 함 (FileInputStream, OutputStream)
6. 전송이 끝나면 연결 해제
*/
public class Server {
public static void main(String[] args) {
System.out.println("Before accept()");
try(
ServerSocket svr = new ServerSocket(1123);
Socket skt = svr.accept();
ObjectInputStream ois = new ObjectInputStream(skt.getInputStream());
OutputStream os = skt.getOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(os);
){
System.out.println("After accept()");
String title = ois.readUTF();
File f = new File(title);
boolean b = f.exists();
System.out.println(b);
if(b){
oos.writeInt(200);
oos.flush();
InputStream file = new BufferedInputStream(new FileInputStream(title));
int r = 0;
while((r =file.read()) != -1){
System.out.println("파일 전송 준비");
os.write(r);
os.flush();
}
file.close();
//파일이 길이를 리턴한다. (long 형 자료에 주의)
System.out.println(f.length());
}else{
oos.writeInt(404);
oos.flush();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
Day 2
1. package Lecture.Week2;
public class Test11 {
public static void main(String[] args){
String l = "HelloWorld";
String t = l.substring(2,5);
String r = "HellWorld";
String t1 = l.substring(2,5);
System.out.println( r== l ); //StringPool형태로 나와서 -> false
/*""로 생성한 String은 POOl을 쓴다. 포인터가 비교 가능 , 그 외의 경우(substring) 은 pool쓴다는 보장이 없다
* 그떄는 equals로 비교한다.*/
System.out.println("llo" == t);//""로 비교하면 틀리게 나올수도 있따 -> false
System.out.println("llo".equals(t)); //true
int r2 = Integer.parseInt("100");
System.out.println( r2 == 100);//true
/*문자열을 숫자로 변환시에 : Double.parseDouble() 있음*/
String tl = "10101,100";
int idx = tl.indexOf(",");
System.out.println(tl.substring(0,idx));
System.out.println(tl.substring(idx + 1)); //아래 것보다 더 메모리 향상에 도움이 됨 . 아래는 몇개의 배열이 될 지 모르니까 / , 하나 정도 있을때 좋음
String[] ls = tl.split(",");//,가 여러 개 있는 경우 이 방법이 편함
System.out.println(ls[0]);
System.out.println(ls[1]);
}
}
/*false
false
true
true
10101
100
10101
100*/
2. 데이터베이스 (Mysql)
데이터베이스를 먼저 구축 -> 안에 테이블 생성
mysql> show databases;
mysql> create database study;
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| study |
| test |
+--------------------+
5 rows in set (0.00 sec)
mysql>use study; //사용하는 데이터베이스로 변경
mysql> create table study01t( //study01t 생성
-> id int not null, //자료형 ; int(4byte)
-> score tinyint not null //자료형 : tinyint(1byte)
-> );
Query OK, 0 rows affected (0.01 sec)
mysql>drop table study01t; //테이블 지우기
mysql>insert into study01t values (10101, 100);//테이블에 값 입력
mysql>insert into study01t values(10102, 90);
mysql> select * from study01t;
+-------+-------+
| id | score |
+-------+-------+
| 10101 | 100 |
| 10102 | 90 |
| 10103 | 80 |
+-------+-------+
3 rows in set (0.00 sec)
mysql>insert into study01t (score, id) //입력시 순서 바꾸어서 입력할 수 있다
-> values(90, 10104);
Query OK, 1 row affected (0.00 sec)
mysql> select * from study01t;
+-------+-------+
| id | score |
+-------+-------+
| 10101 | 100 |
| 10102 | 90 |
| 10103 | 80 |
| 10104 | 90 |
+-------+-------+
4 rows in set (0.00 sec)
-테이블에 있어야하는 개념
- 필드 (Field) - 컬럼
- 자료형을 지정한다(int, tinyint)
- 같은 자료형의 같은 의미의 값이 와야한다
- 레코드(Record) - ROW
- 입력의 단위
- 데이터들이 연관되어진 묶음
=> 이 두가지 개념이 있어야 테이블이라고 할 수 있다.
mysql> delete from study01t where id = 10101; //where 조건을 만족하는 레코드를 없앤다.
Query OK, 1 row affected (0.01 sec)
mysql> select * from study01t;
+-------+-------+
| id | score |
+-------+-------+
| 10102 | 90 |
| 10103 | 80 |
| 10104 | 90 |
+-------+-------+
3 rows in set (0.00 sec)
mysql> delete from study01t where id <10104;
Query OK, 2 rows affected (0.00 sec)
mysql> select * from study01t;
+-------+-------+
| id | score |
+-------+-------+
| 10104 | 90 |
+-------+-------+
1 row in set (0.00 sec)
mysql> delete from study01t; //조건을 주지 않으면 다 지운다.
Query OK, 1 row affected (0.01 sec)
mysql> delete from study01t where 0 = 1; //모든 레코드가 만족하지 않아 지워지지 않음
mysql> delete from study01t where 1 = 1; //모든 레코드가 만족하니까 모두 지워짐
mysql> update study01t set score=90 where id = 10101; //조건만족 하는 것만 업데이트 해줌
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> update study01t set score = score - 10 where id = 10101; //수식 연산 조건도 가능 , 기존의 값 사용 가능
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> update study01t set score = id - 10000 where id = 10101; //같은 레코드의 다른 필드의 값을 가져와서도 변경 가능
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from study01t;
+-------+-------+
| id | score |
+-------+-------+
| 10101 | 101 |
| 10102 | 90 |
| 10103 | 80 |
| 10104 | 90 |
+-------+-------+
4 rows in set (0.00 sec)
mysql> update study01t set score = id - 10000 where id != 10101;
Query OK, 3 rows affected (0.00 sec)
Rows matched: 3 Changed: 3 Warnings: 0
mysql> select * from study01t;
+-------+-------+
| id | score |
+-------+-------+
| 10101 | 80 |
| 10102 | 102 |
| 10103 | 103 |
| 10104 | 104 |
+-------+-------+
4 rows in set (0.00 sec)
mysql> update study01t set id = 0, score = 0 where id = 10101; //두 칼럼이 변경 시에는 "," 사용
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from study01t;
+-------+-------+
| id | score |
+-------+-------+
| 0 | 0 |
| 10102 | 102 |
| 10103 | 103 |
| 10104 | 104 |
+-------+-------+
4 rows in set (0.00 sec)
mysql> select score+5, id from study01t //select는 데이터를 가공해서 보여줄 수있다.
-> where id != 0;
+---------+-------+
| score+5 | id |
+---------+-------+
| 107 | 10102 |
| 108 | 10103 |
| 109 | 10104 |
+---------+-------+
3 rows in set (0.00 sec)
mysql> select score + 5 as sungjuk, id from study01t where id != 0; //컬럼 이름 바꿔서 출력 하지만 실제로 바뀐 것 아니라 보여지는 거만 바꾸어짐
+---------+-------+
| sungjuk | id |
+---------+-------+
| 107 | 10102 |
| 108 | 10103 |
| 109 | 10104 |
+---------+-------+
3 rows in set (0.00 sec)
mysql> select score , score as sungjuk from study01t; //하나의 칼럼을 여러번 출력해도 무방하다.
+-------+---------+
| score | sungjuk |
+-------+---------+
| 0 | 0 |
| 102 | 102 |
| 103 | 103 |
| 104 | 104 |
+-------+---------+
4 rows in set (0.00 sec)
mysql> create table study02t(
-> id char(5) not null,
-> name varchar(10) null
-> );
Query OK, 0 rows affected (0.02 sec)
insert into study02t values('a0001', 'abcd'); //문자열 : ''로 감싼다. char or varchar 자료형
//char : 고정길이 문자열 (학번, 주민번호) / 처리속도가 훨씬 빠름
-> 'a01' 넣어도 무조건 5자리 차지 (낭비 각오)
//varchar : 길이를 최대값까지 설정해주지만 가변적이다 //처리 속도가 조금 느림
-> 'apple'을 넣으면 5자리만 공간 사용 , (낭비 적다)
mysql> select concat(id, '*') from study02t;
//oracle : 'a01 *'
+-----------------+
| concat(id, '*') |
+-----------------+
| a0001* |
| a0001* |
| a0001* |
+-----------------+
3 rows in set (0.00 sec)
mysql> select * from Studentt where addr = '역삼동'; //역삼동에 사는 모든 학생들 검색
mysql> select * from Studentt where addr LIKE '역%'; //역으로 시작하는 문장 검색
mysql> select * from Studentt where addr LIKE '%삼동'; //삼동으로 끝나는 문장 검색
mysql> select * from studentt
-> where substr(addr, 1,2) = '역삼';
+-------+-----------+-----------+
| stId | name | addr |
+-------+-----------+-----------+
| 10101 | 홍길동 | 역삼동 |
| 10103 | 이기자 | 역삼동 |
+-------+-----------+-----------+
2 rows in set (0.00 sec)
mysql> select substr(addr, 1,2) from studentt; //부분 문자열 추출 가능
+-------------------+
| substr(addr, 1,2) |
+-------------------+
| 역삼 |
| 개포 |
| 역삼 |
| 한남 |
| 홍제 |
| 한남 |
+-------------------+
6 rows in set (0.00 sec)
mysql> select length(addr) from studentt; //글자 길이 .utf-8인 경우 한글은 3바이트
+--------------+
| length(addr) |
+--------------+
| 9 |
| 9 |
| 9 |
| 9 |
| 9 |
| 9 |
+--------------+
6 rows in set (0.00 sec)
#aggregate functions : 5가지 => 딱 하나의 결과만 나옴
min / max / count / avg / sum
mysql> select * from scoret where subid = 'KOR1';
+-------+-------+-------+
| stId | subId | score |
+-------+-------+-------+
| 10101 | KOR1 | 60 |
| 10102 | KOR1 | 90 |
| 10103 | KOR1 | 70 |
| 10104 | KOR1 | 80 |
| 10105 | KOR1 | 50 |
| 10106 | KOR1 | 60 |
+-------+-------+-------+
6 rows in set (0.00 sec)
mysql> select min(score) from scoret where subid = 'KOR1'; //국어점수 최소값 1개
+------------+
| min(score) |
+------------+
| 50 |
+------------+
1 row in set (0.00 sec)
## studentt , subjectt , scoret 는 얽혀있다 -> 여러개의 테이블이 연관 관계를 가지고 데이터베이스를 구성한다
mysql> select * from scoret where subid ='KOR1'
-> and stid IN( select stid from studentt where addr LIKE '역삼%');
//여러개 나오는 결과를 이용할 떄 IN , NOT IN 을 사용한다
//하나의 쿼리의 결과를 이용해서 다른 쿼리를 돌릴 수 있다 : 서브쿼리: ( ) 로 묶여 있는것
+-------+-------+-------+
| stId | subId | score |
+-------+-------+-------+
| 10101 | KOR1 | 60 |
| 10103 | KOR1 | 70 |
+-------+-------+-------+
2 rows in set (0.00 sec)
mysql> select * from scoret where subid = 'KOR1' and
-> score <= (select avg(Score) from scoret where subid = 'KOR1');
//유일한 서브쿼리의 결과와 비교는 비교연산자를 쓴다
//서브쿼리는 반드시 괄호로 묶어 주어야 한다.
//국어 점수가 평균(68.666)이 안되는 학생
+-------+-------+-------+
| stId | subId | score |
+-------+-------+-------+
| 10101 | KOR1 | 60 |
| 10105 | KOR1 | 50 |
| 10106 | KOR1 | 60 |
+-------+-------+-------+
3 rows in set (0.00 sec)
mysql> select avg(score) from scoret where subid = 'MAT1' and stid in (select stid from studentt where name like '김%'); //김씨 성을 가진 학생들의 수학 평균
+------------+
| avg(score) |
+------------+
| 70.0000 |
+------------+
1 row in set (0.00 sec)
mysql> update scoret set score = score - 5 where subid = 'ENG1' and stid in ( select * from (select stid from scoret where subid = 'ENG1' and score <= 70) AS X); // 영어 70점 이하의 점수를 받은 학생들의 성적을 -5하라
"AGGREAGATE FUNCTION 은 GROUP BY , HAVING 과 연동된다"
mysql> select stid, avg(score) from scoret group by stid; //stid에 동일한 값을 가진 레코드를 짜매어 평균낸 결과
+-------+------------+
| stid | avg(score) |
+-------+------------+
| 10101 | 76.6667 |
| 10102 | 93.3333 |
| 10103 | 76.6667 |
| 10104 | 73.3333 |
| 10105 | 63.3333 |
| 10106 | 66.6667 |
+-------+------------+
6 rows in set (0.00 sec)
select stid, avg(score) form scoret group by stid where avg(score) <=75; error
-> 왜 ? where은 통계처리에 우선한다.
해서 having은 통계처리 이후에 동작한다.
select stid, avg(score) from scoret group by stid having avg(score) <= 75;
"" 서브쿼리는 크게 3종류로 나뉜다 . ""
1. where 절의 서브쿼리
2. from 절의 서브쿼리 ( inline view )
3. select 절의 서브쿼리 ( 엄청난 결과 / 엄청난 부담 )
from 절의 서브쿼리 : select 결과를 마치 table처럼 보면 된다.
select stid, avg(score) as xx from scoret group by stid;
+-------+------+
| stid | xx |
+-------+------+
| 10101 | 77 |
| 10102 | 93 |
| 10103 | 77 |
| 10104 | 72 |
| 10105 | 62 |
| 10106 | 67 |
+-------+------+
select stid, round(avg(score), 2) as xx from scoret group by stid;
+-------+-------+
| stid | xx |
+-------+-------+
| 10101 | 76.67 |
| 10102 | 93.33 |
| 10103 | 76.67 |
| 10104 | 71.67 |
| 10105 | 61.67 |
| 10106 | 66.67 |
+-------+-------+
//round(): 반올림 하기
select * from ( select stid, round(avg(score), 2) as xx
from scoret group by stid) where xx <= 75;
mysql> create view score2v as
-> select stid, round(avg(score), 2) as xx from
-> scoret group by stid;
Query OK, 0 rows affected (0.01 sec)
mysql> select * from score2v;
+-------+-------+
| stid | xx |
+-------+-------+
| 10101 | 76.67 |
| 10102 | 93.33 |
| 10103 | 76.67 |
| 10104 | 73.33 |
| 10105 | 63.33 |
| 10106 | 66.67 |
+-------+-------+
6 rows in set (0.00 sec)
# 뷰는 실제로 데이터가 존재하는 테이블이 아니라 테이블 데이터를 이용해서 만들어진 하나의 결과 화면일 뿐 이다.
# 뷰를 대상으로 수정 삭제는 무의미 하다.
mysql> select stid, name, (select avg(score) from scoret) as avg from studentt;
+-------+-----------+---------+
| stid | name | avg |
+-------+-----------+---------+
| 10101 | 홍길동 | 75.0000 |
| 10102 | 고길동 | 75.0000 |
| 10103 | 이기자 | 75.0000 |
| 10104 | 박기자 | 75.0000 |
| 10105 | 김영삼 | 75.0000 |
| 10106 | 김대중 | 75.0000 |
+-------+-----------+---------+
6 rows in set (0.00 sec)
mysql> select x.stid, x.name from studentt as x; //studentt 가 너무 기니까 x로 바꾸어 쓴다
mysql> select studentt.stid, studentt.name from studentt; //테이블명.컬럼명 식
+-------+-----------+
| stid | name |
+-------+-----------+
| 10101 | 홍길동 |
| 10102 | 고길동 |
| 10103 | 이기자 |
| 10104 | 박기자 |
| 10105 | 김영삼 |
| 10106 | 김대중 |
+-------+-----------+
mysql> select x.stid, x.name, (select avg(score) from scoret where stid = x.stid) as avg from studentt as x;
+-------+-----------+---------+
| stid | name | avg |
+-------+-----------+---------+
| 10101 | 홍길동 | 76.6667 |
| 10102 | 고길동 | 93.3333 |
| 10103 | 이기자 | 76.6667 |
| 10104 | 박기자 | 73.3333 |
| 10105 | 김영삼 | 63.3333 |
| 10106 | 김대중 | 66.6667 |
+-------+-----------+---------+
6 rows in set (0.00 sec)
mysql> select x.stid, x.avg from(select stid, avg(score) as avg from scoret group by stid)as x;
+-------+---------+
| stid | avg |
+-------+---------+
| 10101 | 76.6667 |
| 10102 | 93.3333 |
| 10103 | 76.6667 |
| 10104 | 73.3333 |
| 10105 | 63.3333 |
| 10106 | 66.6667 |
+-------+---------+
create table temp01t as
->select stid, avg(score) as avg from
->scoret group by stid;
+-------+---------+
| stid | avg |
+-------+---------+
| 10101 | 76.6667 |
| 10102 | 93.3333 |
| 10103 | 76.6667 |
| 10104 | 73.3333 |
| 10105 | 63.3333 |
| 10106 | 66.6667 |
+-------+---------+
6 rows in set (0.00 sec)
mysql> select x.stid, x.avg,(select count(*)+1 from temp01t where avg > x.avg) as rank from temp01t as x; //등수
+-------+----------+------+
| stid | avg | rank |
+-------+----------+------+
| 10101 | 100.0000 | 1 |
| 10102 | 93.3333 | 2 |
| 10103 | 76.6667 | 3 |
| 10104 | 73.3333 | 4 |
| 10105 | 63.3333 | 6 |
| 10106 | 66.6667 | 5 |
+-------+----------+------+
서브쿼리가 여섯명의 등수를 구할 떄 쿼리가 6*6으로 36번이나 돌아야한다 . 만약 1000명이라면? 말이안됨
-> 임시 테이블을 만들자
mysql> select * from temp02t order by rank;
+-------+----------+------+
| stid | avg | rank |
+-------+----------+------+
| 10101 | 100.0000 | 1 |
| 10102 | 93.3333 | 2 |
| 10103 | 76.6667 | 3 |
| 10104 | 73.3333 | 4 |
| 10106 | 66.6667 | 5 |
| 10105 | 63.3333 | 6 |
+-------+----------+------+
6 rows in set (0.00 sec)
mysql> select * from temp02t order by rank desc;
+-------+----------+------+
| stid | avg | rank |
+-------+----------+------+
| 10105 | 63.3333 | 6 |
| 10106 | 66.6667 | 5 |
| 10104 | 73.3333 | 4 |
| 10103 | 76.6667 | 3 |
| 10102 | 93.3333 | 2 |
| 10101 | 100.0000 | 1 |
+-------+----------+------+
6 rows in set (0.00 sec)
-임시테이블과 뷰는 흩어진 데이터에서 자신이 원하는 데이터로 가공할 수 있는 방법 제공(비정형 데이터에서 정형화 된 데이터를 만들어 낸다)
-뷰는 오버헤드가 있지만 데이터 변경을 즉각 반영한다 / 임시테이블은 오버헤드가 적지만, 데이터의 변경을 즉각 반영 못함
-select 서브쿼리는 오버헤드가 크다 (1000명의 등수를 처리하는 결과를 1000명이 동시 열람하면 100만건의 쿼리가 동작하는 셈 -> group by 오버헤드 포함)
-임시 테이블은 이런 부담을 극적으로 줄여준다
mysql> create table study3t(
-> no int not null auto_increment primary key,
-> theTime datetime not null
-> );
mysql> insert into study3t values(default, now());
Query OK, 1 row affected (0.01 sec)
mysql> select * from study3t;
+----+---------------------+
| no | theTime |
+----+---------------------+
| 1 | 2019-07-23 17:16:05 |
| 2 | 2019-07-23 17:16:16 |
+----+---------------------+
2 rows in set (0.00 sec)
now() : 현재 시간 => 입력 시 datetime 자료형 쓴다.
//datetime 자료형에 들어있는 값은 연산이 가능하다.
mysql> select no, date_add(theTime, INTERVAL 1 MONTH) from study3t;
+----+-------------------------------------+
| no | date_add(theTime, INTERVAL 1 MONTH) |
+----+-------------------------------------+
| 1 | 2019-08-23 17:16:05 |
| 2 | 2019-08-23 17:16:16 |
+----+-------------------------------------+
2 rows in set (0.00 sec)
mysql> select no, date_add(theTime, INTERVAL 4 DAY) from study3t;
+----+-----------------------------------+
| no | date_add(theTime, INTERVAL 4 DAY) |
+----+-----------------------------------+
| 1 | 2019-07-27 17:16:05 |
| 2 | 2019-07-27 17:16:16 |
+----+-----------------------------------+
2 rows in set (0.00 sec)
mysql> select no, date_add(theTime, INTERVAL 4 HOUR) from study3t;
+----+------------------------------------+
| no | date_add(theTime, INTERVAL 4 HOUR) |
+----+------------------------------------+
| 1 | 2019-07-23 21:16:05 |
| 2 | 2019-07-23 21:16:16 |
+----+------------------------------------+
2 rows in set (0.00 sec)
//날짜 데이터를 다룰 때 연산의 필요성이 없으면 char 쓴다.
mysql> create table study04t(
-> no int not null auto_increment primary key,
-> theTime char(19) not null
-> );
Query OK, 0 rows affected (0.02 sec)
mysql> insert into study04t values (default, now());
Query OK, 1 row affected (0.01 sec)
mysql> select * from study04t;
+----+---------------------+
| no | theTime |
+----+---------------------+
| 1 | 2019-07-23 17:27:03 |
+----+---------------------+
1 row in set (0.00 sec)
'Language Study > Java' 카테고리의 다른 글
제주에서 자바_Week2_3 (0) | 2019.07.25 |
---|---|
제주에서 자바_Week2_2 (0) | 2019.07.24 |
제주에서 자바_Week1 (0) | 2019.07.20 |
4. 클래스 (0) | 2019.05.29 |
3. 참조 타입 (0) | 2019.05.28 |