이번 포스팅에서는 DBMS의 개념, 유의사항과 같은 배경 이론과 JDBC를 활용한 테이블형 DB의 기본 작동과, 데이터 관리 실습에 대한 내용을 다루었다.
1. DBMS의 개념
1) What? : "DBMS란?"
: 데이터베이스를 관리해주는 프로그램 혹은 시스템이다. 본인의 블로그에서는 오라클을 사용하여 포스팅 될 예정이다.
2) Why? : "왜 존재하고, 왜 관리하는데?"
: 여러 사람들이 공유하여 사용하는 것을 목표로 하기 때문
3) How? : "어떤식으로 관리할건지?"
- 데이터의 구성 : 모델링. ex) 학번, 이름, 학과, 성적, 나이, 성별, 전화번호, 주소, ...
- 데이터의 사용 : SQL의 조작
- 데이터의 가공 : JDBC의 사용
4) DB를 다룰때 유의사항
- 중복제거 : 씽크가 맞지 않는 현상과 데이터 낭비를 방지해야한다. (ex. 학교 & 동아리에서의 학생정보관리 통일)
- 가용성을 상승시켜 관리 : 항상 접근 가능해야 한다. 사용자의 요청에 상시로 반응해야한다. (ex. 쇼핑몰재고부족)
- 기밀성 유지 : 이용자가 권한을 가지고 있는지 확인이 필요하다. (ex. 웹툰 유료분 볼 수 있는지 체크하는 과정)
- 무결성 유지 : 데이터의 변조를 막는 것
즉, DB를 다룰때 일관성, 무결성, 보안성유지를 유의해야하며, 이는 정보보호 3요소의 내용과도 연관이 깊다.
*정보보호 3요소(CIA)*
- Confidentiality 기밀성 : 허가된 사용자만 접근
- Integrity 무결성 : 허가된 사용자만,해당 대상에 대해서만 수정,삭제
- Availability 가용성 : 사용 필요시 항상 가능해야 함
2. 테이블형 DB_기초
1) 작업 전 처리
- 프로젝트에서 SQL파일 생성
- connection의 Name을 변경하면 Type이 함께 전환되는 것을 확인할 수 있다.
- [프로젝트 파일] -> 우클릭 -> [Properities]
- [Java Build Path]탭 -> [Libraries] -> [Add External JARs...]클릭 -> 별도 설치한 "orcle6"연동! -> [Apply and Close]
1, 2번의 작업은 매 SQL파일 생성시마다 진행 / 3, 4번의 작업은 Project파일에서 처음 SQL파일 생성시마다 진행해주어야 한다.
2) SQL파일 활용 기초_TableDB생성
- TableDB의 생성
varchar(문자열의 byte) : 문자열 1개에 약 2, 3byte정도로 계산이 된다. 입력받을 최대글자수를 염려하여 초기설정 할 것.--주석처리의 방법이 상이한 것을 확인 가능-- select * from all_tables; --TableDB 생성-- create table student( snum int primary key, sname varchar (10) ); --데이터 추가-- insert into student values(1, '홍길동'); insert into student values(2, '티모'); --TableDB 조회-- select * from student;
- 데이터 저장_조회를 위한 Results창 세팅 오른쪽 하단의 SQL Results창을 통해서 데이터의 상황을 확인하기 위해서는 해당 순서의 진행을 통해 view를 작동시켜야한다. "이클립스 상단의 [Window] -> [Show View] -> [Other] -> 'SQL Results'검색 -> 실행"
- 데이터 현황 조회_SQL파일에서의 명령어 수행 실행할 명령어를 드래그 한 후 Alt + X 입력을 통해 SQL파일에서 명령어 수행을 진행할 수 있다. 이때 출력명령어인 select * from 클래스명; 을 진행하면, 오른쪽 하단에 실행 성공 / 실패 유무와 Results창에서 현재 데이터 상황을 곧장 조회할 수 있다.
3) TableDB사용_기초
: 새로운 java파일을 생성하여 해당 파일에서 SQL파일 접근 및 접근한 데이터베이스를 사용하는 방법.
*DB 접근과 사용은 아래와 같이 4개의 단계로 진행된다.*
- DBMS에 맞는 드라이버 데이터 로드
- DB에 연결
- 데이터를 read, write
- ★DB와의 연결을 해제★ : 자원 낭비와 속도저하 방지 & 다음 연결에 문제 발생을 야기하므로 중요하다.
package class01;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;
public class Test001 {
public static void main(String[] args) {
// 1. DBMS에 맞는 드라이버 데이터를 로드
// 2. DB에 연결
// 3. 데이터를 read,write
// 4. DB와의 연결을 해제☆
final String driverName="oracle.jdbc.driver.OracleDriver";
//*하단 사진참고*
final String url="jdbc:oracle:thin:@localhost:1521:xe";
final String user="ham";
final String passwd="1234";
//이용범위를 고려한 배치
Connection conn=null;
Statement stmt=null;
Scanner sc = new Scanner(System.in);
System.out.println("학번입력 : ");
int snum = sc.nextInt();
System.out.println("이름입력 : ");
String sname = sc.next();
try {
Class.forName(driverName); // -> 1
conn=DriverManager.getConnection(url,user,passwd); // -> 2
// -> 3
stmt=conn.createStatement(); //데이터불러오기
stmt.executeQuery("insert into student values(" + snum + ",'" + sname + "')");//작성하기
System.out.println("로그: 데이터 작성완료");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
stmt.close();
conn.close(); // -> 4
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
finally는 오류의 유무와 상관없이 진행되는 부분이기에 그점을 활용하여 하단에 데이터를 닫는 작업을 진행한다. 즉, 오류와 상관없이 데이터는 사용후 바로 닫혀야한다.
[출력화면 : ★ -> 입력]
학번입력 :
3
이름입력 :
왕밤빵
로그: 데이터 작성완료
[SQL Results]
* 사진참고 주석 : 데이터 불러오기를 위한 URL, User, Password 확인 *
- 오른쪽 하단의 New Oracle 우클릭 -> [Properties] 클릭 2. Driver Properties탭에서 내용 확인
4) ResultSet_데이터 복사
: 성질이 Iterator와 유사하다. 데이터의 본체를 한칸씩 찍어서 복사해내는 개념이다. 복사하면서 출력해내는것도 가능하나, 보통의 경우 배열리스트를 사용하여 VO에 하나씩 옮겨 저장할 목적으로 사용된다.
package class01;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class Test02 {
public static void main(String[] args) {
final String driverName="oracle.jdbc.driver.OracleDriver";
final String url="jdbc:oracle:thin:@localhost:1521:xe";
final String user="ham";
final String passwd="1234";
// 컬럼:속성을 지정하게 되면 선택보기가 가능하다
final String sql = "select * from student";
Connection conn=null;
Statement stmt=null;
try {
Class.forName(driverName); // -> 1
conn=DriverManager.getConnection(url,user,passwd); // -> 2
stmt=conn.createStatement(); // -> 3
//ResultSet : 데이터 그 자체
ResultSet rs = stmt.executeQuery(sql);
while(rs.next()) { //rs에 값 있냐?
//있으면 rs에서 getInt("snum")가져와봐, 그리고 가져온거 출력해
System.out.println("학번데이터 : "+rs.getInt("snum"));
System.out.println("이름데이터 : "+rs.getString("sname"));
}
rs.close(); //알아서 닫히지만 그래도...!
System.out.println("로그: 데이터 작성완료");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
stmt.close();
conn.close(); // -> 4
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
이전 내용 대비 추가된 내용은 final String SQL변수 , ResultSet의 선언, rs를 사용한 while문과 rs.close( );이다. 이때 rs.getInt : rs.getString메서드는 인자를 index로 두는 경우와 String으로 작성하는 것, 총 두가지로 오버로딩 되어있다. final String으로 지정해놓은 SQL변수의 포함영역에 따라 각각 사용할 수 있다.
- 인자가 index인 경우
: 조회하는 sql이 *(All)이 아닐때 사용가능하며 기재된 순서대로 index가 1부터 부여된다. 아래 첨부된 사진과 같은 인자를 가진 메서드로 사용하면 되고, getint와 getString중 타입에 맞춰 사용하면 된다.final String sql = "select snum, sname from student"; ResultSet rs = stmt.executeQuery(sql); while(rs.next()) { System.out.println("학번데이터 : "+rs.getInt(1));//타입따라 System.out.println("이름데이터 : "+rs.getString(2));//타입따라 } rs.close();
- 인자가 String인 경우
: 조회하는 sql이 *(all)일때 사용가능하다. 위의 서식과 같이 작성하면 된다.final String sql = "select * from student"; ResultSet rs = stmt.executeQuery(sql); while(rs.next()) { System.out.println("학번데이터 : "+rs.getInt("snum"));//타입따라 System.out.println("이름데이터 : "+rs.getString("sname"));//타입따라 } rs.close();
5) Iterator_데이터저장
: 위의 ResutlSet작업과 함께 진행되는 것이 일반적이다. 배열리스트를 통해 VO로 복사된 내용을 iterator를 통해 저장하고, 그것을 출력할 수 있다. 예제와 함께 설명이 진행된다.
Q. 상품을 2개 입력받고, 가격이 가장 비싼 제품명을 출력할 것
- Table DB
select * from all_tables; create table product( snum int primary key, --제품명 길이를 고려한 byte설정-- sname varchar (20), sprice int ); insert into product values (1001, '엄청 긴팔티', 5000); insert into product values (1002, '후드 없는 티', 16000); select * from product;
- main
package class01; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.Scanner; //VO의 역할 class Product{ private int snum; private String sname; private int sprice; public int getSnum() { return snum; } public void setSnum(int snum) { this.snum = snum; } public String getSname() { return sname; } public void setSname(String sname) { this.sname = sname; } public int getSprice() { return sprice; } public void setSprice(int sprice) { this.sprice = sprice; } //출력을 배열 출력을 대비한 오버라이딩 @Override public String toString() { return "Product [snum=" + snum + ", sname=" + sname + ", sprice=" + sprice + "]"; } } public class Test03 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); final String driverName = "oracle.jdbc.driver.OracleDriver"; final String url="jdbc:oracle:thin:@localhost:1521:xe"; final String user="ham"; final String passwd="1234"; //sql속성:칼럼 지정을 통해 -> 삽입과 출력을 각각 저장 final String sql_insert = "insert into product values ("; final String sql_select = "select sname,sprice from product"; //VO에 옮겨 담는데에 사용할 배열리스트 ArrayList<Product> datas=new ArrayList<Product>(); Connection conn = null; Statement stmt = null; try { //1번째 데이터 불러오기 전 드라이버 불러오기 Class.forName(driverName); //2번째 작업(변수는 상단에 선언) conn = DriverManager.getConnection(url, user, passwd); stmt = conn.createStatement(); for(int i=0; i<2; i++) { //상품 두번 추가받을거임 //입력받을 내용 System.out.println("상품번호 : "); int snum = sc.nextInt(); System.out.println("상품명 : "); String sname = sc.next(); System.out.println("가격 : "); int sprice = sc.nextInt(); stmt.executeQuery(sql_insert+snum+", '"+sname+"', "+sprice+")"); } //데이터를 하나씩 읊고, 그걸 하나씩 배열리스트에 담는 로직 ResultSet rs = stmt.executeQuery(sql_select); while(rs.next()) { // 상품명 : 00원 System.out.println(rs.getString(1)+" : "+rs.getInt(2)+"원"); //snum은 필요 없으니, name과 price만 배열에 담음 Product data = new Product(); data.setSname(rs.getString(1)); data.setSprice(rs.getInt(2)); datas.add(data); } rs.close(); } catch (Exception e) { //최상위 익셉션으로 수정 // TODO Auto-generated catch block e.printStackTrace(); } finally { try { stmt.close(); conn.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } //최대값 찾는 로직 : 리스트 사용 int maxP=datas.get(0).getSprice(); int maxI=0; for(int i=1;i<datas.size();i++) { if(maxP<datas.get(i).getSprice()) { maxP=datas.get(i).getSprice(); maxI=i; } } //그리고 제일 비싼 제품명 출력 System.out.println(datas.get(maxI).getSname()); } }
(출력 및 데이터 결과 조회 생략)
3. 테이블DB_SQL속성 : 컬럼
1) 구성 기본 설정
: TableDB를 생성할때 구성에 필요한 지정값에 대한 내용이다.
create table student(
snum int primary key,
sname varchar (10) not null
score int default 0,
--기본값 : 현재날짜--
reg date default sysdate
);
- primary key : 제약조건이다. 즉, null일 수 없으며, 유일해야한다.
- not null : 제약조건이다. 즉, null일 순 없으나 유일할 필요는 없다.
- default : 자동으로 지정한 기본값을 넣어준다.
SQL파일에서는 대소문자를 구분하지 않아 카멜표기법을 사용하지 않는다.
2) 구조변경
: alter을 활용하여 구성을 추가할 수 있으며, 지정한 varchar의 byte를 변경할 수 있다.
alter table student add(phone varchar(15));
alter table student modify(sname varchar(20));
- alter add : 괄호에 담긴 내용을 구성에 추가할 수 있다.
- alter modify : 지정한 구성의 byte 값을 변경할 수 있다.
+값을 넣을 구성을 지정하고, 그 구성에 각각 값을 넣는 방법+
: 비울것은 비우며 선택적 입력이 가능하다.
insert into student (snum, sname, phone) values(4, 왕밤빵, 01012341234);
--값 넣을 구성 지정-- --각각 저장할 값 입력--
add를 통해 전화번호입력칸 생성이 되었으나, 데이터 조회시 전화번호 구성추가 이전에 생성된 애들은 다 phone조회 결과가 null이다. 때문에 가능한 구조조정이 없도록 설계해야한다.
3) 지정조회
: 원하는 구성만 선택하는것이 가능하다.
-- * : All --
select * from student;
--select 선택할 구성 form 클래스명--
select snum from student;
select sname from student;
select snum, sname from student;
--<데이터의 정렬 : varchar도 가능>--
select * from student order by snum desc;--오름차순--
select * from student order by snum asc;--내림차순--
--구성(멤버변수)의 총 개수--
select count(*) from student;
4) 조건절
: 주로 검색할때 많이 사용된다.
--'아'로 시작하는 데이터--
select * from sudent where sname like '아%';
--'아'가 들어가는 데이터--
select * from sudent where sname like '&아%';
--'아'로 끝나는 데이터--
select * from sudent where sname like '%아';
--응용 : 3이상인 snum을 오름차순 정렬--
select * from student where snum >= 3 order by snum desc;
조건절을 활용하여 다양한 응용이 가능함을 확인할 수 있다.
5) 수정과 삭제
: 조건절이 활용되어 데이터의 수정이 가능해지며, 추가로 삭제 명령어도 확인해보자
-- 1snum의 sname을 a로 바꿔줘 --
update student set sname='a' where snum=1;
-- snum이 2이하인 데이터 전부 삭제 --
delete from student where snum<=2;
-- tableDB 자체 삭제:생성된 적 없듯이 --
drop table 클래스명;
- update : 수정
- delete : 데이터 삭제
- drop : 테이블 삭제
6) pk++하여 삽입
: 위의 속성들을 응용하면 sum의 존재하는 데이터중 가장 큰 값+1을 하여 데이터를 추가할 수도 있다.
insert into student values((select nvl(max(snum),0)+1,from student),'티모');
--nvl(snum의 max가 null이라면, 0을 사용할게)--
DB에서는 자료형이 int라 해도, 입력되지 않은 값은 0이 아닌 null로 표시된다.
때문에 nvl(왼쪽의 값이 null이라면, 이쪽을 사용할게)의 사용이 필수이다.
sql컬럼을 메인에 변수로 선언하여 메인에서도 간편하고, 자유롭게 접근할 수 있다.
'DBMS' 카테고리의 다른 글
[Oracle] 웹크롤링_기초 (0) | 2022.01.24 |
---|---|
[Oracle] 트랜잭션 (0) | 2022.01.22 |
[Oracle] pstmt (0) | 2022.01.21 |
[Oracle] DB접근&MVC분리 (0) | 2022.01.20 |
[Oracle] 설치와 오류 (0) | 2022.01.18 |