21.10.04 - 웹 개발 입문 36일차
데이터베이스 - 인덱스(Index)
INDEX(인덱스, 색인)
= 데이터베이스 테이블의 컬럼에 설치하는 도구
= 검색속도 향상
= 유니크(Unique) 또는 기본키(Primary key)에는 인덱스가 자동 생성된다.
일반 인덱스 : create index 이름 on 테이블(컬럼)
create index name_index on product(name);
유니크 인덱스 : create unique index 이름 on 테이블(컬럼)
create unique index no_index on product(no);
인덱스 제거
drop index name_index;
index의 불균형을 재조정하는 명령
alter index name_index rebuild;
JDBC - 개요 및 접속
오라클 데이터베이스로의 접속(로그인) 시도
자바에서는 데이터베이스가 꼭 오라클이 아니어도 상관이 없다.
= 자바에서 오라클 정보를 기본적으로 알아야 하나?
= 오라클에 관련된 정보를 자바에게 알려줄 필요가 있다.
= 프로젝트 우클릭 -> [build path] -> [configure build path] -> [libraries] -> [add JARs] -> ojdbc8.jar 추가
package connect;
public class Test01 {
public static void main(String[] args) throws ClassNotFoundException {
Class.forName("oracle.jdbc.OracleDriver");
System.out.println("오라클 드라이버 설치 완료");
}
}
로그인 수행 - 연결(접속) 생성 - Connection 생성
= 필요한 정보 : 전송위치정보, 아이디, 비밀번호
package connect;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class Test02 {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//드라이버 설치 코드
Class.forName("oracle.jdbc.OracleDriver");
System.out.println("오라클 드라이버 설치 완료!");
//Connection con = DriverManager.getConnection(위치정보, 아이디, 비밀번호);
Connection con = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "계정아이디", "계정비밀번호");
System.out.println("로그인 성공!");
//명령 준비 및 전송 , 실행 및 결과 확인을 이곳에서 수행
//접속 종료
con.close();
}
}
(ex) database에 insert 명령을 전송하여 데이터를 추가하도록 지시
package jdbc.insert;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class Test01 {
public static void main(String[] args) throws SQLException, ClassNotFoundException {
Class.forName("oracle.jdbc.OracleDriver");
Connection con = DriverManager.getConnection(
"jdbc:oracle:thin:@localhost:1521:xe", "계정아이디", "계정비밀번호");
//1. 명령문 준비
String sql = "insert into menu(menu_name, menu_price, menu_type) "
+ "values('갈치조림', 7000, '식사')";
//2. 전송객체 대여
PreparedStatement ps = con.prepareStatement(sql);
//3. 실행
ps.execute();
con.close();
System.out.println("실행 완료!");
}
}
Q : 변수에 저장된 값이 menu 테이블에 insert 될 수 있도록 JDBC 구문을 작성해보세요.
String menuName="오므라이스";
String menuType ="식사";
int menuPrice = 8500;
package jdbc.insert;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class Test02 {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
String menuName="오므라이스";
String menuType ="식사";
int menuPrice = 8500;
Class.forName("oracle.jdbc.OracleDriver");
Connection con = DriverManager.getConnection(
"jdbc:oracle:thin:@localhost:1521:xe", "계정아이디", "계정비밀번호");
String sql = "insert into menu(menu_name, menu_price, menu_type) "
+ "values('"+menuName+"', '"+menuPrice+"', '"+menuType+"')";
PreparedStatement ps = con.prepareStatement(sql);
ps.execute();
con.close();
System.out.println("실행 완료!");
}
}
최종 insert 형태
직접 구문을 더하여 만드는 방식의 문제점
1. 구문 형태를 보기 어렵다(문자열, 숫자, 날짜에 따른 표시 방식이 다르다)
2. 구문에서 사용하는 글자들을 값으로 추가할 수 없다. 혼선이 발생한다.(ex : KH's스페셜)
3. SQL Injection 공격이 발생할 수 있다.(입력값에 구문을 넣어서 정보를 탈취하는 기법)
=> 해결책 : 전송객체(PreparedStatement)에게 데이터 설정을 위임
=> 문제점 : 구문의 완성된 형태를 알 수 없다.
package jdbc.insert;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class Test03 {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
String menuName= "팥빙수";
int menuPrice = 5000;
String menuType = "디저트";
Class.forName("oracle.jdbc.OracleDriver");
Connection con = DriverManager.getConnection(
"jdbc:oracle:thin:@localhost:1521:xe","계정아이디", "계정비밀번호");
//동적 SQL 생성 방식에서는 위치 홀더(?)를 사용하여 데이터가 들어갈 자리를 표시
//-> PreparedStatement를 이용해서 위치 홀더에 어떤 형태의 데이터를 채울 것인지 명을 내린다
String sql = "insert into menu(menu_name, menu_price, menut_type) values(?, ?, ?)";
PreparedStatement ps = con.prepareStatement(sql);
ps.setString(1, menuName);//1번 위치홀더(?)에 menuName을 String 형태로 채울거에요!
ps.setInt(2, menuPrice);//2번 위치홀더(?)에 menuPrice를 int 형태로 채울거에요!
ps.setString(3, menuType);//3번 위치홀더(?)에 menuType을 String 형태로 채울거에요!
ps.execute();//시킨대로 가서 실행하세요!
con.close();
}
}
Q. 사용자에게 필요한 정보를 입력받아서 exam 테이블에 데이터를 등록하는 프로그램을 구현
문제 없이 등록이 되었다면 마지막에 "등록 성공!" 이라는 메세지 출력
package jdbc.insert;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Scanner;
public class Test04_1 {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
Scanner sc = new Scanner(System.in);
System.out.print("이름 : ");
String student = sc.next();
System.out.print("과목 : ");
String subject = sc.next();
System.out.print("유형 : ");
String type = sc.next();
System.out.print("점수 : ");
int score = sc.nextInt();
sc.close();
Class.forName("oracle.jdbc.OracleDriver");
Connection con = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "계정아이디", "계정비밀번호");
// String sql = "insert into exam values(exam_seq.nextval, '또가스', 'SQL활용', '서술형', 70)";
String sql = "insert into exam values(exam_seq.nextval, ?, ?, ?, ?)";
PreparedStatement ps = con.prepareStatement(sql);
ps.setString(1, student);
ps.setString(2, subject);
ps.setString(3, type);
ps.setInt(4, score);
ps.execute();
con.close();
System.out.println("등록이 완료되었습니다");
}
}
Q. 사용자에게 필요한 정보를 입력받아서 product 테이블에 데이터를 등록하는 프로그램을 구현
문제 없이 등록이 되었다면 마지막에 "등록 성공!" 이라는 메세지 출력
package jdbc.insert;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Scanner;
public class Test05_3 {
public static void main(String[] args) throws Exception {
// 준비 : 등록에 필요한 데이터
Scanner sc = new Scanner(System.in);
System.out.print("번호 : ");
int no = sc.nextInt();
System.out.print("이름 : ");
String name = sc.next();
System.out.print("종류 : ");
String type = sc.next();
System.out.print("가격 : ");
int price = sc.nextInt();
System.out.print("생산날짜 : ");
String made = sc.next();
System.out.print("유통기한 : ");
String expire = sc.next();
sc.close();
// 처리 : 데이터베이스 등록
Class.forName("oracle.jdbc.OracleDriver");
Connection con = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "계정아이디", "계정비밀번호");
String sql = "insert into product values(" + "?,"
+ "?, ?, ?, to_date(?, 'YYYY-MM-DD'), to_date(?, 'YYYY-MM-DD')" + ")";
PreparedStatement ps = con.prepareStatement(sql);
ps.setInt(1, no);
ps.setString(2, name);
ps.setString(3, type);
ps.setInt(4, price);
ps.setString(5, made);
ps.setString(6, expire);
ps.execute();
con.close();
// 완료 : 메세지 출력
System.out.println("등록 완료!");
}
}
Q. 사용자에게 필요한 정보를 입력받아서 회원가입을 구현(member 테이블 사용)
문제 없이 등록이 되었다면 마지막에 "회원가입 성공!" 이라는 메세지 출력
문제가 생겼다면 "회원 가입 과정에서 오류가 발생했습니다" 라는 메세지 출력
package jdbc.insert;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLIntegrityConstraintViolationException;
import java.util.Scanner;
public class Test06_3 {
public static void main(String[] args) {
try {
//입력
Scanner sc = new Scanner(System.in);
System.out.print("아이디 : ");
String memberId = sc.next();
System.out.print("비밀번호 : ");
String memberPw = sc.next();
System.out.print("닉네임 : ");
String memberNick = sc.next();
System.out.print("생년월일 : ");
String memberBirth = sc.next();
System.out.print("이메일 : ");
String memberEmail = sc.next();
System.out.print("연락처 : ");
String memberPhone = sc.next();
sc.close();
//처리
Class.forName("oracle.jdbc.OracleDriver");
Connection con = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "계정아이디", "계정비밀번호");
//#1. 형식을 지정할 경우
String sql1 = "insert into member("
+ "member_id, "
+ "member_pw, "
+ "member_nick, "
+ "member_birth, "
+ "member_email, "
+ "member_phone"
+ ") values(?, ?, ?, to_date(?, 'YYYY-MM-DD'), ?, ?)";
//#2. 형식을 지정하지 않을 경우
String sql2 = "insert into member values(?, ?, ?, to_date(?, 'YYYY-MM-DD'), ?, ?, sysdate, 100, '준회원')";
PreparedStatement ps = con.prepareStatement(sql2);
ps.setString(1, memberId);
ps.setString(2, memberPw);
ps.setString(3, memberNick);
ps.setString(4, memberBirth);
ps.setString(5, memberEmail);
ps.setString(6, memberPhone);
ps.execute();
con.close();
//출력
System.out.println("회원 가입이 완료되었습니다");
}
catch(SQLIntegrityConstraintViolationException e) {
System.out.println("아이디 또는 닉네임이 사용중입니다");
}
catch(Exception e) {
System.out.println("회원 가입 과정에서 오류가 발생했습니다");
}
}
}
Q. 과제
## jdbc.delete.Test01
사용자에게 상품번호(no)를 입력받아서 product 테이블에서 해당하는 상품번호 데이터를 삭제
package jdbc.delete;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.util.Scanner;
public class Test01 {
public static void main(String[] args) throws Exception {
Scanner sc = new Scanner(System.in);
System.out.print("상품번호를 입력하세요 : ");
int no = sc.nextInt();
sc.close();
Class.forName("oracle.jdbc.OracleDriver");
Connection con = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "계정아이디", "계정비밀번호");
String sql = "delete from product where no = ?";
PreparedStatement ps = con.prepareStatement(sql);
ps.setInt(1, no);
// ps.execute();
int count = ps.executeUpdate();
if (count > 0) {
System.out.println(count + "개의 상품이 삭제 되었습니다.");
} else {
System.out.println("상품이 존재하지 않습니다.");
}
ps.close();
con.close();
}
}
## jdbc.delete.Test02
사용자에게 아이디(memberId)와 비밀번호(memberPw)를 입력받아 일치하는 회원 정보를 삭제
package jdbc.delete;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.util.Scanner;
public class Test02 {
public static void main(String[] args) throws Exception {
Scanner sc = new Scanner(System.in);
System.out.print("아이디를 입력하세요 : ");
String memberId = sc.next();
System.out.print("비밀번호를 입력하세요 : ");
String memberPw = sc.next();
sc.close();
Class.forName("oracle.jdbc.OracleDriver");
Connection con = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "계정아이디", "계정비밀번호");
String sql = "delete from member where member_id = ? and member_pw = ?";
PreparedStatement ps = con.prepareStatement(sql);
ps.setString(1, memberId);
ps.setString(2, memberPw);
int count = ps.executeUpdate();
if (count > 0) {
System.out.println("아이디가 삭제 되었습니다.");
} else {
System.out.println("잘못 입력했습니다.");
}
ps.close();
con.close();
}
}