반응형
# 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 예외) 발생
생성자 설명
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

+ Recent posts