1. 4차 정규화
2. 비정규화
3. 물리 모드
4. java 및 oracle 연결 삽입
1) === OracleDriver(오라클 드라이버)의 역할, 2) 자리 표시자 참고
5. Java 및 Oracle 연결을 선택합니다.
1) ResultSet 인터페이스의 Main 메소드
================================================== ===============
3차 정규화가 나타나는지 확인해보자.
https://mdh2057.45
어제의 마지막 설명 사진
위 파일은 정규화 과정을 설명하는 파일입니다.
(출처: 서영학 강사)
하나. 4. 정규화
논리적이라면 주문과 판매가 전부입니다.
모든 것이 가능합니까?
all : all (1 : all OR all : 1 )로 만들지 않는 것이 물리적인 경우 4차 정규화가 호출됩니다.
한 사람이 여러 제품을 구매할 때
여러 사람이 제품을 구매할 때
–> 잘못된 4차 정규화
— 올바른 4차 정규화
— 4. 정규화 완료
2. 비정규화
–> 비정규화는 정규화 후 필요에 따라 추가하는 것을 의미합니다.
정규화 과정을 통해 값을 가져오려고 할 때 가져올 때마다 JOIN 작업의 처리 속도에 영향을 미치므로 비정규화 과정을 건너뛰게 됩니다.
3. 물리 모드
모든 exERD를 완료하려면 논리 모드에서 수행한 작업과 마찬가지로 모든 것을 물리적 모드에 두어야 합니다.
속성에서 테이블의 물리적 이름을 변경할 수 있습니다.
열에서 데이터 유형, 물리적 이름 및 NOT NULL을 설정할 수도 있습니다.
Constraints 탭에 Check Constraints를 넣고 조건을 지정하고 코멘트를 추가하면 팀원들이 정확히 무엇인지 알 것입니다.
Index 탭에서 Primary Key Unique를 설정할 수도 있습니다.
— 물리학 모드 과정(전문 부분, 교육 부분만 수정됨)
4. java 및 oracle 연결 삽입
Java와 Oracle을 연결하려면 ojdbc+.jar이 참조 라이브러리에 있어야 합니다.
Java와 Oracle을 연결하는 명령문은 다음과 같습니다.
연결 연결 = 영;
// 연결 연결 데이터베이스 서버에 연결하는 Java 개체입니다.
준비된 진술 쉿 = 영;
// 준비된 문장 쉿 은
// 연결 연결(연결된 DB 서버)로 보낼 SQL 문(편지)을 전송(배달)하는 객체(메일 배달 서비스)입니다.
1) === OracleDriver의 역할 ===
하나). OracleDriver를 메모리에 로드합니다.
2). OracleDriver 개체를 만듭니다.
삼). DriverManager에 OracleDriver 개체를 등록합니다.
–> DriverManager는 벡터에 여러 드라이버를 저장하고 관리하는 클래스입니다.
자바와 오라클을 연결하려면
1. Oracle 드라이버를 로드해야 합니다.
2. 연결할 Oracle 서버를 결정합니다.
3. SQL 문(편집기)을 만듭니다.
4. 연결된 Oracle 서버(Conn)에 SQL 문(레터)을 전달하기 위해 PreparedStatement 객체(Postman)를 생성합니다.
5. PreparedStatement(postman) 객체는 실행을 위해 준비된 SQL 문(문자)을 Oracle 서버로 보내야 합니다.
6. 사용한 캐리어 반환 // 반환 순서는 생성 순서의 역순입니다.
2) 자리 표시자 참고
위치보유자는 귀하의 ID와 비밀번호를 제3자가 볼 수 없도록 하는 데 사용됩니다.
?를 통해 제3자가 내 정보를 해킹하는 것을 방지하는 것이 목표입니다.
사용.
전)
선 SQL = “tbl_memo(no, name, msg)에 붙여넣기”
+ ” 값(seq_memo.nextval, ?, ?) “ ;
==> SQL을 볼 때 결과가 없습니다.
결과: sql ==> tbl_memo(no, name, msg) values(seq_memo.nextval, ?, ?)에 삽입
? 나왔는데 모르겠어
포지션 홀더를 사용하지 않는 경우
전)
선 SQL =” tbl_memo(no, name, 소식) “
+ ” values(seq_memo.nextval, ‘”+이름+”‘, ‘”+소식+”‘)” ;
— 위와 같이 변수의 값을 직접 SQL문에 넣으면 외부에서 입력한 데이터 값이 그대로 표시되기 때문에 보안상 위험합니다.
결과: sql ==> tbl_memo(no, name, msg) values(seq_memo.nextval, 홍길동, 아버지는 아버지…)에 삽입
내가 넣은거랑 똑같아서 위험해!
!
—> Java에서 Oracle을 입력하자 .(코드를 자세히 보세요)
— 자바 부분
package jdbc.day01;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Scanner;
public class DML_insert_PreparedStatement_01 {
public static void main(String() args) {
Connection conn = null;
// Connection conn 은 데이터베이스 서버와 연결을 맺어주는 자바의 객체이다.
PreparedStatement pstmt = null;
// PreparedStatement pstmt 은
// Connection conn(연결한 DB 서버)에 전송할 SQL문(편지)을 전송(전달)을 해주는 객체(우편배달부)이다.
Scanner sc = new Scanner(System.in);
try {
// >>> 1. 오라클 드라이버 로딩 <<< //
/*
=== OracleDriver(오라클 드라이버)의 역할 ===
1). OracleDriver 를 메모리에 로딩시켜준다.
2). OracleDriver 객체를 생성해준다.
3). OracleDriver 객체를 DriverManager에 등록시켜준다.
--> DriverManager 는 여러 드라이버들을 Vector 에 저장하여 관리해주는 클래스이다.
*/
Class.forName("oracle.jdbc.driver.OracleDriver");
// >>> 2. 어떤 오라클 서버에 연결을 할래? <<< //
System.out.print("▷ 연결할 오라클 서버의 IP 주소 : ");
String ip = sc.nextLine();
//oracle_user을 하나 생성
conn = DriverManager.getConnection("jdbc:oracle:thin:@"+ip+":1521:xe", "JDBC_USER", "gclass");
// === Connection conn 기본값은 auto commit이다 === //
// === Connection conn 기본값은 auto commit을 수동 commit 으로 전환하겠습니다.
=== //
// (rollback 가능하게 만들기 위해)
conn.setAutoCommit(false); // 이것이 수동 commit 을 뜻한다 ture일 경우에는 자동 commit(안적어도 자동 commit)
// >>> 3. SQL문(편지)을 작성한다.
<<< //
System.out.print("▷ 글쓴이 : ");
String name = sc.nextLine();
System.out.print("▷ 글내용 : ");
String msg = sc.nextLine();
/*
String sql = " insert into tbl_memo(no, name, msg) "
+ " values(seq_memo.nextval, '"+name+"', '"+msg+"') " ;
위와 같이 변수의 값을 직접 sql문에 대입시켜 버리면 외부에서 입력한 데이터값이 보여지므로 보안상 위험해집니다.
그래서 아래처럼 위치홀더(?)를 사용합니다.
*/
String sql = " insert into tbl_memo(no, name, msg) "
+ " values(seq_memo.nextval, ?, ?) " ;
// ? 를 "위치홀더" 라고 부른다!
!
!
!
!
!
!
!
// SQL문 뒤에 ; 를 넣으면 오류이다.
!
!
!
!
!
!
!
// >>> 4. 연결한 오라클 서버(conn)에 SQL문(편지)을 전달할 객체 PreparedStatement 객체(우편배달부) 생성하기 <<< //
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, name); // 1부터 시작함 위에서 받아온 name을 넣어주겠다 ? 였지만 name으로 넣어줌
// 1 은 String sql 에서 첫번째 위치홀더(?)를 말한다, 첫번째 위치홀더(?) 에 name 을 넣어준다.
pstmt.setString(2, msg); // 2 은 String sql 에서 두번째 위치홀더(?)를 말한다, 두번째 위치홀더(?) 에 msg 을 넣어준다.
System.out.println("sql ==> " + sql);
// >>> 5. PreparedStatement 객체(우편배달부)는 작성된 SQL문(편지)을 오라클 서버에 보내서 실행이 되도록 해야 한다.
<<< //
int n = pstmt.executeUpdate(); // return 타입은 int 형
/*
.executeUpdate(); 은 SQL문이 DML문(insert, update, delete, merge) 이거나
SQL문이 DDL문(create, drop, alter, truncate) 일 경우에 사용된다.
SQL문이 DML문이라면 return 되어지는 값은 적용되어진 행의 개수를 리턴시켜준다.
예를 들어, insert into ... 하면 1 개행이 입력되므로 리턴값은 1 이 나온다.
update ... 할 경우에 update 할 대상의 행의 개수가 5 이라면 리턴값은 5 가 나온다.
delete ... 할 경우에 delete 되어질 대상의 행의 개수가 3 이라면 리턴값은 3 이 나온다.
SQL문이 DDL문(create, alter 등등)이라면 return 되어지는 값은 무조건 0 이 리턴된다.
참고
.executeQuery(); 은 SQL문이 DQL문(select) 일 경우에 사용된다.
*/
System.out.println("n => " + n);
if(n == 1)
{
String yn = "";
do
{
//////////////////////////////////////////////////////////////////
System.out.print("▷ 정말로 입력하시겠습니까? (Y/N) : ");
yn = sc.nextLine();
if("y".equalsIgnoreCase(yn)) // 대소문자 y이면
{
conn.commit(); // 커밋
System.out.println(" >>> 데이터 입력 성공!
!
<<< ");
}
else if("n".equalsIgnoreCase(yn)) // 대소문자 n이면
{
conn.rollback(); // 롤백
System.out.println(" >>> 데이터 입력 취소!
!
!
<<< ");
}
else
{
System.out.println(" >>> Y 또는 N 만 입력하세요!
!
!
<<< \n");
}
///////////////////////////////////////////////////////////////////
} while( !
("y".equalsIgnoreCase(yn) || "n".equalsIgnoreCase(yn)));
}
}
catch (ClassNotFoundException e)
{
System.out.println(">>> ojdbc8.jar 파일이 없습니다.
<<<");
}
catch (SQLException e)
{
e.printStackTrace();
}
// 반납하기
finally {
// 6. 사용하였던 자원을 반납하기
// 반납의 순서는 생성순서의 역순으로 한다.
try {
if(pstmt !
= null)
{
pstmt.close(); //null 이 존재하기에 null 이 아니면 정상 종료
pstmt = null;
}
if(conn !
= null)
{
conn.close(); //null 이 존재하기에 null 이 아니면 정상 종료
pstmt = null;
}
}
catch (SQLException e)
{
e.printStackTrace();
}
}
sc.close();
System.out.println("~~~~~~ 프로그램 종료 ~~~~~~~");
}// end of main
}
— 오라클 부분
----- **** 오라클 계정 생성하기 시작 **** ------
-- 오라클 계정 생성을 위해서는 SYS 또는 SYSTEM 으로 연결하여 작업을 해야 합니다(SYS 시작)
show user;
-- USER이(가) "SYS"입니다.
-- 오라클 계정 생성시 계정명 앞에 c## 붙이지 않고 생성하도록 하겠습니다.
alter session set "_ORACLE_SCRIPT" = true;
-- Session이(가) 변경되었습니다.
-- 오라클 계정명은 JDBC_USER 이고 암호는 gclass 인 사용자 계정을 생성합니다.
-- 위에것을 안해면 create user c##JDBC_USER 이렇게 해야한다.
create user JDBC_USER identified by gclass default tablespace users;
-- User JDBC_USER이(가) 생성되었습니다.
-- 위에서 생성되어진 JDBC_USER 이라는 오라클 일반 사용자 계정에게 오라클 서버에 접속이 되어지고,
-- 테이블 생성 등등을 할 수 있도록 여러가지 권한을 부여해주겠습니다.
grant connect, resource, create view, unlimited tablespace to JDBC_USER;
-- Grant을(를) 성공했습니다.
----- **** 오라클 계정 생성하기 끝 **** ------
show user;
-- USER이(가) "JDBC_USER"입니다.
-- 테이블 생성하기
create table tbl_memo
(no number(4)
,name Nvarchar2(20) not NULL
,msg Nvarchar2(100) not NULL
,writeday date default SYSDATE
,constraint PK_tbl_memo_no primary key(no)
);
-- Table TBL_MEMO이(가) 생성되었습니다.
-- 시퀀스 생성하기
create sequence seq_memo
start with 1
increment by 1
nomaxvalue
nominvalue
nocycle
nocache;
-- Sequence SEQ_MEMO이(가) 생성되었습니다.
-------- 자바에서 인서트를 해올것이다.
--------
-- 현재상황
select *
from tbl_memo
order by 1;
-- 1 민동현 안녕하세요~~ 23/02/21
-- 3 이순신 좋은 하루되세요~ 23/02/21
-- 2번이 없는 이유는 자바에서 commit을 하지 않고 rollback; 을 했기 때문에 2번을 건너뛰고 3번이 나오는 것이다.
– 결과는 오라클
5. Java 및 Oracle 연결을 선택합니다.
1) ResultSet 인터페이스의 Main 메소드
1. next() : 선택한 결과에서 커서를 다음으로 이동 반환형은 boolean
2. first() : 선택한 결과의 첫 번째로 커서를 이동합니다.
반환 유형은 부울입니다.
3. last() : 선택한 결과의 끝으로 커서를 이동합니다.
반환 유형은 부울입니다.
== 커서가 있는 행에서 컬럼 값을 읽어오는 방식 ==
getInt(숫자): 칼럼 타입이 숫자이고 정수로 읽을 경우 파라미터 번호는 칼럼의 위치값
getInt(character): 칼럼 타입이 숫자이고 정수로 읽을 경우 파라미터 character는 칼럼 이름 또는 별칭
getLong(number): 칼럼 타입이 숫자이고 정수로 읽으면 파라미터 번호는 칼럼의 위치 값
getLong(character): 칼럼 타입이 숫자형이고 정수로 읽을 경우 파라미터 character는 칼럼 이름 또는 별칭
getFloat(Number): 컬럼 타입이 숫자이고 실수로 읽은 경우, 파라미터 번호는 해당 컬럼의 위치 값
getFloat(문자): 컬럼 타입이 숫자이고 실수로 읽은 경우 매개변수 문자는 컬럼 이름 또는 별칭
getDouble(숫자): 칼럼 타입이 숫자이고 실수로 읽은 경우 파라미터 번호는 칼럼의 위치값
getDouble(문자): 칼럼 타입이 숫자이고 실수로 읽은 경우 파라미터 문자는 칼럼 이름 또는 별칭
getString(숫자): 칼럼 타입을 문자열로 읽으면 파라미터 번호는 칼럼의 위치값
getString(문자): 컬럼 타입을 문자열로 읽는 경우, 매개변수 문자는 컬럼 이름 또는 별칭입니다.
— Java에서 5단계에서 붙여넣은 결과를 가져와서 실행해 봅시다.
(코드를 잘 보세요)
— 자바 부분
package jdbc.day01;
import java.sql.*;
import java.util.Scanner;
public class DQL_select_PreparedStatement_02 {
public static void main(String() args) {
Connection conn = null;
// Connection conn 은 데이터베이스 서버와 연결을 맺어주는 자바의 객체이다.
PreparedStatement pstmt = null;
// PreparedStatement pstmt 은
// Connection conn(연결한 DB 서버)에 전송할 SQL문(편지)을 전송(전달)을 해주는 객체(우편배달부)이다.
ResultSet rs = null;
// ResultSet rs 은 select 되어진 결과물이 저장되어지는 곳.
Scanner sc = new Scanner(System.in);
try {
// >>> 1. 오라클 드라이버 로딩 <<< //
/*
=== OracleDriver(오라클 드라이버)의 역할 ===
1). OracleDriver 를 메모리에 로딩시켜준다.
2). OracleDriver 객체를 생성해준다.
3). OracleDriver 객체를 DriverManager에 등록시켜준다.
--> DriverManager 는 여러 드라이버들을 Vector 에 저장하여 관리해주는 클래스이다.
*/
Class.forName("oracle.jdbc.driver.OracleDriver");
// >>> 2. 어떤 오라클 서버에 연결을 할래? <<< //
System.out.print("▷ 연결할 오라클 서버의 IP 주소 : ");
String ip = sc.nextLine();
//oracle_user을 하나 생성
conn = DriverManager.getConnection("jdbc:oracle:thin:@"+ip+":1521:xe", "JDBC_USER", "gclass");
// >>> 3. SQL문(편지)을 작성한다.
<<< //
String sql = " select no, name, msg, to_char(writeday, 'yyyy-mm-dd hh24:mi:ss') AS writeday "
+ " from tbl_memo "
+ " order by no desc ";
// SQL문 뒤에 ; 를 넣으면 오류이다.
!
!
!
!
!
!
!
// SQL 문을 작성할 때 1줄 마다 잎, 뒤로 공백을 꼭 주도록 한다.
// >>> 4. 연결한 오라클 서버(conn)에 SQL문(편지)을 전달할 객체 PreparedStatement 객체(우편배달부) 생성하기 <<< //
pstmt = conn.prepareStatement(sql);
// >>> 5. PreparedStatement 객체(우편배달부)는 작성된 SQL문(편지)을 오라클 서버에 보내서 실행이 되도록 해야 한다.
<<< //
rs = pstmt.executeQuery();
// SQL문이 DQL문(select) 이므로 ,executeQuery(); 이다
// pstmt.executeQuery(); 을 실행하면 select 되어진 결과물을 가져오는데 그 타입은 ResultSet 으로 가져온다.
System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
System.out.println("글번호\t글쓴이\t글내용\t작성일자");
System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
/*
=== 인터페이스 ResultSet 의 주요한 메소드 ===
1. next() : select 되어진 결과물에서 커서를 다음으로 옮겨주는 것 리턴타입은 boolean
2. first() : select 되어진 결과물에서 커서를 가장 처음으로 옮겨주는 것 리턴타입은 boolean
3. last() : select 되어진 결과물에서 커서를 가장 마지막으로 옮겨주는 것 리턴타입은 boolean
== 커서가 위치한 행에서 컬럼의 값을 읽어들이는 메소드 ==
getInt(숫자) : 컬럼의 타입이 숫자이면서 정수로 읽어들이때
파라미터 숫자는 컬럼의 위치값
getInt(문자) : 컬럼의 타입이 숫자이면서 정수로 읽어들이때
파라미터 문자는 컬럼명 또는 alias명
getLong(숫자) : 컬럼의 타입이 숫자이면서 정수로 읽어들이때
파라미터 숫자는 컬럼의 위치값
getLong(문자) : 컬럼의 타입이 숫자이면서 정수로 읽어들이때
파라미터 문자는 컬럼명 또는 alias명
getFloat(숫자) : 컬럼의 타입이 숫자이면서 실수로 읽어들이때
파라미터 숫자는 컬럼의 위치값
getFloat(문자) : 컬럼의 타입이 숫자이면서 실수로 읽어들이때
파라미터 문자는 컬럼명 또는 alias명
getDouble(숫자) : 컬럼의 타입이 숫자이면서 실수로 읽어들이때
파라미터 숫자는 컬럼의 위치값
getDouble(문자) : 컬럼의 타입이 숫자이면서 실수로 읽어들이때
파라미터 문자는 컬럼명 또는 alias명
getString(숫자) : 컬럼의 타입이 문자열로 읽어들이때
파라미터 숫자는 컬럼의 위치값
getString(문자) : 컬럼의 타입이 문자열로 읽어들이때
파라미터 문자는 컬럼명 또는 alias명
*/
StringBuilder sb = new StringBuilder();
while(rs.next()) { // 리턴 타입은 boolean 그 다음 행이 있으면 true 없으면 false
/*
rs.next() 는 select 되어진 결과물에서 위치(행의 위치)를 다음으로 옮긴 후
행이 존재하면 true 를 리턴해주고, 행이 없으면 false 를 리턴해주는 메소드이다.
*/
int no = rs.getInt("NO"); // "NO" 은 select 해온 컬럼명이다.
(대문자로 쓰지 않아도 됨)
// 또는
//int no = rs.getInt(1); // 1 은 select 해온 컬럼의 위치값으로서 1번째 컬럼을 가리키는 것이다.
String name = rs.getNString("NAME"); // "NAME" 은 select 해온 컬럼명이다.
(대문자로 쓰지 않아도 됨)
// 또는
//String name = rs.getNString(2); // 2 는 select 해온 컬럼의 위치값으로서 2번째 컬럼을 가리키는 것이다.
String msg = rs.getNString("MSG"); // "MSG" 은 select 해온 컬럼명이다.
(대문자로 쓰지 않아도 됨)
// 또는
//String msg = rs.getNString(3); // 3 는 select 해온 컬럼의 위치값으로서 3번째 컬럼을 가리키는 것이다.
String WRITEDAY = rs.getNString("WRITEDAY"); // "WRITEDAY" 은 select 해온 컬럼명이다.
(대문자로 쓰지 않아도 됨)
// 또는
//String WRITEDAY = rs.getNString(2); // 4 는 select 해온 컬럼의 위치값으로서 4번째 컬럼을 가리키는 것이다.
sb.append(no);
sb.append("\t" + name);
sb.append("\t" + msg);
sb.append("\t" + WRITEDAY + "\n");
} // end of while (rs.next())
System.out.println(sb.toString());
}
catch (ClassNotFoundException e)
{
System.out.println(">>> ojdbc8.jar 파일이 없습니다.
<<<");
}
catch (SQLException e)
{
e.printStackTrace();
}
// 반납하기
finally {
// 6. 사용하였던 자원을 반납하기
// 반납의 순서는 생성순서의 역순으로 한다.
try {
if(rs !
= null)
{
rs.close();
rs = null;
}
if(pstmt !
= null)
{
pstmt.close(); //null 이 존재하기에 null 이 아니면 정상 종료
pstmt = null;
}
if(conn !
= null)
{
conn.close(); //null 이 존재하기에 null 이 아니면 정상 종료
conn = null;
}
}
catch (SQLException e)
{
e.printStackTrace();
}
}
sc.close();
System.out.println("~~~~~~ 프로그램 종료 ~~~~~~~");
}// end of main
}
— 오라클 부분
----- **** 오라클 계정 생성하기 시작 **** ------
-- 오라클 계정 생성을 위해서는 SYS 또는 SYSTEM 으로 연결하여 작업을 해야 합니다(SYS 시작)
show user;
-- USER이(가) "SYS"입니다.
-- 오라클 계정 생성시 계정명 앞에 c## 붙이지 않고 생성하도록 하겠습니다.
alter session set "_ORACLE_SCRIPT" = true;
-- Session이(가) 변경되었습니다.
-- 오라클 계정명은 JDBC_USER 이고 암호는 gclass 인 사용자 계정을 생성합니다.
-- 위에것을 안해면 create user c##JDBC_USER 이렇게 해야한다.
create user JDBC_USER identified by gclass default tablespace users;
-- User JDBC_USER이(가) 생성되었습니다.
-- 위에서 생성되어진 JDBC_USER 이라는 오라클 일반 사용자 계정에게 오라클 서버에 접속이 되어지고,
-- 테이블 생성 등등을 할 수 있도록 여러가지 권한을 부여해주겠습니다.
grant connect, resource, create view, unlimited tablespace to JDBC_USER;
-- Grant을(를) 성공했습니다.
----- **** 오라클 계정 생성하기 끝 **** ------
show user;
-- USER이(가) "JDBC_USER"입니다.
-- 테이블 생성하기
create table tbl_memo
(no number(4)
,name Nvarchar2(20) not NULL
,msg Nvarchar2(100) not NULL
,writeday date default SYSDATE
,constraint PK_tbl_memo_no primary key(no)
);
-- Table TBL_MEMO이(가) 생성되었습니다.
-- 시퀀스 생성하기
create sequence seq_memo
start with 1
increment by 1
nomaxvalue
nominvalue
nocycle
nocache;
-- Sequence SEQ_MEMO이(가) 생성되었습니다.
---------- 자바에서 select를 해줄 것이다.
--------
-- select 문 일때 실행한곳
select no, name, msg, to_char(writeday, 'yyyy-mm-dd hh24:mi:ss') AS writeday
from tbl_memo
order by no desc;
— Java의 결과 부분