* 클래스 : 객체의 구조를 정의하는 곳 (속성(필드, 멤버변수), 생성자, 함수(메서드)) * 객체(인스턴스) : 클래스로부터 생성되며 new 생성자함수() 이용해서 생성함 * new 연산자 : 객체 생성 연산자이며, 생성자함수를 호출하고, 힙 메모리 영역에 객체를 저장함 * 사용법 : 클래스 객체변수 = new 생성자함수();* 객체변수 : 힙 메모리 주소(방번호)가 저장됨
package chap06.sec02.exam01;
/**
* packageName : chap06.sec02.exam01
* fileName : Car
* author : GGG
* date : 2023-09-19
* description : 자동차 클래스
* 요약 :
* 클래스 : 객체의 구조를 정의하는 곳 (속성(필드, 멤버변수), 생성자, 함수(메서드))
* 객체(인스턴스) : 클래스로부터 생성되며 new 생성자함수() 이용해서 생성함
* new 연산자 : 객체 생성 연산자이며, 생성자함수를 호출하고, 힙 메모리 영역에 객체를 저장함
* 사용법 : 클래스 객체변수 = new 생성자함수();
* 객체변수 : 힙 메모리 주소(방번호)가 저장됨
*
* <p>
* ===========================================================
* DATE AUTHOR NOTE
* —————————————————————————————
* 2023-09-19 GGG 최초 생성
*/
public class Car {
// 클래스의 3요소 : 속성, 생성자함수, 함수(메서드)
// TODO: 속성(필드, 멤버변수)
String compnay = "현대자동차";
String model = "그랜저";
String color = "검정";
int maxSpeed = 350;
int speed; // 기본 초기화(0)
}
package chap06.sec02.exam01;
/**
* packageName : chap06.sec02.exam01
* fileName : CarApplication
* author : GGG
* date : 2023-09-19
* description : 실행 클래스
* 요약 :
* <p>
* ===========================================================
* DATE AUTHOR NOTE
* —————————————————————————————
* 2023-09-19 GGG 최초 생성
*/
public class CarApplication {
public static void main(String[] args) {
// 객체 생성 : 클래스명 객체변수명 = new 생성자함수();
// 생성자 함수명 == 클래스명
Car car = new Car();
// TODO: 클래스의 속성 출력하기
// 사용법 : 객체변수명.속성명
System.out.println("제작회사 : "+ car.compnay);
System.out.println("모델명 : "+ car.model);
System.out.println("색상 : "+ car.color);
System.out.println("최고속도 : "+ car.maxSpeed);
System.out.println("현재속도 : "+ car.speed); // 기본값 출력
// car 클래스 속성값 수정 수정
// 현재속도를 수정해보기 (car.speed)
car.speed = 60;
// 결과출력
System.out.println("수정된 현재속도 : "+ car.speed);
}
}
자동 속성 초기화
속성을 선언만 하고 출력할 때 기본값이 무엇인지 알아봅시다.
package chap06.sec02.exam02;
/**
* packageName : chap06.sec02.exam02
* fileName : FieldInit
* author : GGG
* date : 2023-09-20
* description : 자동 속성 초기화
* 요약 :
* <p>
* ===========================================================
* DATE AUTHOR NOTE
* —————————————————————————————
* 2023-09-20 GGG 최초 생성
*/
public class FieldInit {
// TODO: 클래스의 3요소 = 속성(필드), 생성자함수, 함수(메서드)
// 정수 : byte, short, int, long
byte bField;
short sField;
int iField;
long lField;
// 실수 : float, double
float fField;
double dField;
// char / boolean
char cField;
boolean boField;
// String / int[]
String strField;
int[] arrField;
}
/** * Member 객체를 생성하고 속성에 아래의 값으로 저장한 후 속성의 값을 출력하세요 * 결과 : * 이름 : 최하얀 * id : 23 */
package chap06.sec02.verify;
/**
* packageName : chap06.sec02.verify
* fileName : Member
* author : GGG
* date : 2023-09-20
* description : 회원 정보 클래스
* 요약 :
* <p>
* ===========================================================
* DATE AUTHOR NOTE
* —————————————————————————————
* 2023-09-20 GGG 최초 생성
*/
public class Member {
String name; // 회원명
String id; // 회원 아이디
String password; // 회원 패스워드
int age; // 나이
}
package chap06.sec02.verify;
/**
* packageName : chap06.sec02.verify
* fileName : MemberApplication
* author : GGG
* date : 2023-09-20
* description : 실행클래스
* 요약 :
* <p>
* ===========================================================
* DATE AUTHOR NOTE
* —————————————————————————————
* 2023-09-20 GGG 최초 생성
*/
public class MemberApplication {
public static void main(String[] args) {
/**
* Member 객체를 생성하고 속성에 아래의 값으로 저장한 후 속성의 값을 출력하세요
* 결과 :
* 이름 : 최하얀
* id : 23
*/
Member member = new Member();
member.name = "최하얀";
member.id = "23";
System.out.println("이름 : " + member.name);
System.out.println("id : " + member.id);
}
}
public class Sec0101 {
/**
* Hello World 출력함수
*/
public void exam01(){
// 출력단축키 sout
System.out.println("Hello World");
}
public void exam02(){
// 예제 1) x, y 정수 변수를 만들어서 덧셈결과를 화면에 출력하세요
int x = 1;
int y = 2;
int result = x + y;
System.out.println(result);
}
}
변수
package chap02;
/**
* packageName : chap02
* fileName : Sec0201
* author : GGG
* date : 2023-09-18
* description :
* 요약 :
* 변수 : 값을 저장할 수 있는 메모리 공간
* 변수 사용 범위 : {} 안에서만 사용가능
* 만약에 {} 안에 {}가 있다면 변수는 안에 {} 도 사용가능함
* <p>
* ===========================================================
* DATE AUTHOR NOTE
* —————————————————————————————
* 2023-09-18 GGG 최초 생성
*/
public class Sec0201 {
public void exam01(){
// 변수 선언
int value = 20;
// 변수 연산
// 예제 2) 변수 value에 값을 10 더하는 연산을 한 후 화면에 출력하세요
int result = value + 10;
System.out.println(result);
}
public void exam02(){
// 예제 3) x=3, y=5가 있습니다.
// x와 y 값을 바꾸어서 출력하세요
// swap 코딩
int x = 3;
int y = 5;
// swap 코딩
int temp = x; // x의 값을 임시변수에 넣어둠
x = y; // x의 값이 overwrite 됨
y = temp; // 임시변수 값을 y에 넣음
// 출력
System.out.println("x = " + x +" , y = " + y);
}
/**
* 변수의 허용범위 예제
*/
public void exam04(){
int v1 = 15;
if(v1 > 10){
int v2;
v2 = v1 - 10;
}
// int v3 = v1 + v2 + 5; // v2는 변수 사용불가라서 에러 발생
}
}
기본자료형
package chap02;
/**
* packageName : chap02
* fileName : Sec0202
* author : GGG
* date : 2023-09-18
* description : 기본 자료형(Type)
* 요약 :
* 정수 : byte(1), short(2), int(4, ***), long(8, **)
* char : 2byte 자료형, 문자 1개를 의미, 홑따옴표('')표시
* (저장시 유니코드(숫자)로 저장되고 출력시는 문자로 출력됨)
* String(***) : 쌍따옴표("")로 감싼 문자열을 의미
* 실수 : float(4), double(8, ***)
* boolean : 참/거짓 자료형, true/false
* <p>
* ===========================================================
* DATE AUTHOR NOTE
* —————————————————————————————
* 2023-09-18 GGG 최초 생성
*/
public class Sec0202 {
public void exam01(){
// 1bit : 최소 단위, 8bit = 1byte, 1024byte = 1KB
// 1024KB = 1MB, 1024MB = 1GB, 1024GB = 1TB, 1024TB = 1HB
// 2진수 표현 : 0b 를 붙이면 2진수(0, 1로 표현하는 수)
int var1 = 0b1011; // 2진수(0b 붙이면 2진수)
int var2 = 0206; // 8진수(0 붙이면 8진수)
int var3 = 365; // 10진수
int var4 = 0xB3; // 16진수 (0x를 붙이면 16진수)
System.out.println("var1 : " + var1);
System.out.println("var2 : " + var2);
System.out.println("var3 : " + var3);
System.out.println("var4 : " + var4);
}
public void exam03(){
long var1 = 10; // 정수 8byte
long var2 = 20L; // L 붙이면 long 자료형
System.out.println(var1);
System.out.println(var2);
}
public void exam04(){
// 아스키코드
char c1 = 'A'; // 문자를 직접 저장
char c2 = 65; // 십진수로 저장 => 'A'
System.out.println(c1);
System.out.println(c2);
}
public void exam05(){
String name = "홍길동";
String job = "프로그래머";
System.out.println(name);
System.out.println(job);
}
/**
* 특수기호 : /n, /t, ", \(이스케이프문자)
*/
public void exam06(){
System.out.println("번호\t이름\t직업"); // 탭 문자
System.out.print("행 단위 출력\n"); // 줄바꿈 문자
System.out.println("우리는 \"개발자\" 입니다."); // \" 사용
System.out.println("봄\\여름\\가을\\겨울"); // \\ 사용
}
/**
* 실수 : float(4), double(8, ***)
*/
public void exam07(){
float var2 = 3.14f; // float 사용시 끝에 f 붙임
double var3 = 3.14; // double
System.out.println(var2);
System.out.println(var3);
// e : 지수 표현식
double var6 = 3e6; // 3000000.0
double var7 = 2e-3; // 0.002
System.out.println(var6);
System.out.println(var7);
}
}
형변환
package chap02;
/**
* packageName : chap02
* fileName : Sec0203
* author : GGG
* date : 2023-09-18
* description : 자료형 변환
* 요약 :
* 자동 타입 변환 : 자동으로 자료형이 변환되는 것 : 작은(byte) 자료형 -> 큰 자료형
* 강제 타입 변환 : 강제로 자료형 변환 : 사용법 : (자료형)변수명, 큰 자료형 -> 작은 자료형
* <p>
* ===========================================================
* DATE AUTHOR NOTE
* —————————————————————————————
* 2023-09-18 GGG 최초 생성
*/
/**
* 자동 형변환 예제
*/
public class Sec0203 {
public void exam01(){
byte byteValue = 10; // 1byte 정수형
// 자동 자료형 변환
int intValue = byteValue;
System.out.println("intValue : " + intValue);
// 실수 자동 형변환
float floatValue = 100.5F;
double doubleValue = floatValue;
System.out.println("doubleValue : " + doubleValue);
}
/**
* 강제 형변환 예제
* 참고) 아스키코드 변환 : char 변수 <- int 값 : 아스키코드 -> 문자로 변환
* int 변수 <- char 값 : 아스키코드 변환 <- 문자
*/
public void exam02(){
int intValue = 44032; // 4byte
// char charValue = intValue; // int 4byte, char 2byte 이므로 오류발생 강제형변환 필요
char charValue = (char)intValue; // 강제 형변환
// TODO : char 자료형에 아스키 코드(숫자) 변환 : 아스키코드(숫자) -> 문자로 변환
char alpha = 65; // A
// TODO : 정수형 자료형에 문자 -> 아스키코드로 변환
int beta = 'A'; // 65
System.out.println("charValue : " + charValue);
// double(8) -> int(4) 강제 형변환
double doubleValue = 3.14;
// int intValue2 = doubleValue; // 오류발생
int intValue2 = (int)doubleValue;
System.out.println("intValue : " + intValue2);
}
/**
* 문자열 + 숫자 = 문자열
*/
public void exam06(){
// 결합 연산
String str1 = 10 + 2 + "8"; // 128
System.out.println(str1);
String str2 = 10 + "2" + 8; // 1028
System.out.println(str2);
String str3 = "10" + (2 + 8); // 1010
System.out.println(str3);
}
/**
* 문자열 -> int 자료형 변경 : Integer.parseInt("값");
* int -> 문자열 변경 :
*/
public void exam07(){
// 문자열 -> int 자료형으로 변경
int value1 = Integer.parseInt("10"); // 문자열 -> 정수
double value2 = Double.parseDouble("3.14"); // 문자열 -> 실수
boolean value3 = Boolean.parseBoolean("true"); // 문자열 -> 참/거짓
System.out.println(value1);
System.out.println(value2);
System.out.println(value3);
// int -> 문자열 자료형으로 변경
String str1 = String.valueOf(10); // 정수 -> 문자열로 변경 (속도 빠름)
String str2 = "" + 10; // 빈문자열 + 정수 = 문자열
String str3 = String.valueOf(3.14); // 실수 -> 문자열
String str4 = String.valueOf(true); // 참/거짓 -> 문자열
System.out.println(str1);
System.out.println(str2);
System.out.println(str3);
System.out.println(str4);
}
}
입출력함수 및 문자열 비교함수
package chap02;
import java.util.Scanner;
/**
* packageName : chap02
* fileName : Sec0204
* author : GGG
* date : 2023-09-18
* description :
* 요약 :
* System.out.println() : 화면에 출력하고 줄바꿈 함수
* System.out.print() : 화면에 출력하는 함수
* System.out.printf("%d %s %f", 정수변수, 문자열변수, 실수변수)
* Scanner : 콘솔 입력을 받기 위한 클래스(객체 정의)
* 한라인 입력 받기 함수 : .nextLine();
* 공백까지 입력 받기 함수 : .next();
* 참고) nextInt(), nextDouble() 등...
* <p>
* ===========================================================
* DATE AUTHOR NOTE
* —————————————————————————————
* 2023-09-18 GGG 최초 생성
*/
public class Sec0204 {
public void exam05(){
// 입력받기 : System.in (키보드 입력)
Scanner scanner = new Scanner(System.in);
String inputData; // 입력 문자열
while(true){
inputData = scanner.nextLine(); // 1 라인 입력받기
System.out.println("입력된 문자열 :" + inputData);
// TODO: 코드를 완성하세요 (입력된 문자열이 q가 들어오면 반복문 종료하게)
// TODO: 자바에서 문자열 비교 equal 함수 사용
// 문자열.equals("문자열2") : 같으면 true, 아니면 false
if (inputData.equals("q")) {
break;
}
}
System.out.println("종료");
}
}
연산자
package chap03;
import java.util.Scanner;
/**
* packageName : chap03
* fileName : Sec0301
* author : GGG
* date : 2023-09-18
* description :
* 요약 :
* 산술 : +, -, *, /, %(나머지 연산자)
* 부호 : +, -
* 문자열 붙이기 : +
* 대입연산자 : =, +=, -=, *=, /=, %=
* 증감 : ++, --
* 비교 : ==, !=, >, <, >=, <=,(1문자 비교, 숫자비교) instanaceof
* TODO : 문자열 비교 : 문자열.equals(문자열2)
* 논리 : !, &, |,(비트연산자) &&(논리곱), ||(논리합)
* 삼항 : (조건식)? A : B
* 우선순위 필요하면 () 쓸 것
*
* <p>
* ===========================================================
* DATE AUTHOR NOTE
* —————————————————————————————
* 2023-09-18 GGG 최초 생성
*/
public class Sec0301 {
public void exam01(){
int x = -100;
int result1 = +x;
int result2 = -x;
System.out.println("result1 : " + result1);
System.out.println("result2 : " + result2);
}
public void exam03(){
boolean play = true;
System.out.println(play);
play = !play; // false
System.out.println(play);
}
/**
* 사칙연산 예제 : /(나눗셈) 조심
*/
public void exam04(){
int v1 = 5;
int v2 = 2;
int result = v1 + v2;
System.out.println(result);
System.out.println("---------------------------------");
int result2 = v1 / v2;
System.out.println(result2); // 정수/정수 => 실수부분이 잘림
System.out.println("---------------------------------");
// TODO : 나눗셈 개선 코딩 : 강제 형변환 후 계산해야함
double result3 = (double)v1 / (double)v2;
// double result3 = (double)v1 / v2; // 같은 결과
System.out.println(result3);
}
// 연습문제 : 정수 1개를 입력받아 그대로 출력하기
// 입력 : 5
public void exam05(){
Scanner sc = new Scanner(System.in);
System.out.println(sc.next());
}
// 연습문제2 : 문자 2개 입력받아 순서 바꿔 출력하기
public void exam06(){
Scanner sc = new Scanner(System.in);
String strFirst = sc.next(); // 공백까지 입력받기
String strSecond = sc.next(); // 공백까지 입력받기
System.out.println(strSecond + " " + strFirst);
}
/**
* char : 내부적으로 정수로 저장됨(유니코드 : 아스키코드 확장판(한글, 중국어 등을 표시))
*/
public void exam07(){
char c1 = 'A' + 1; // char(정수) : 'B' ('A' 아스키코드(65) 65 + 1 = 66)
char c2 = 'A';
System.out.println(c1);
System.out.println(c2);
}
// 연습문제3 : char 이용하는 문제
// 값이 'A' 로 주어져 있습니다. 'A' 대문자 이면 대문자이군요 라고 출력하고, 소문자이면 소문자이군요라고 출력, 숫자이면 숫자이군요 라고 출력
public void exam08(){
int charCode = 'A';
if(charCode >= 65 && charCode <= 90) {
System.out.println("대문자이군요");
} else if (charCode >= 97 && charCode <= 122) {
System.out.println("소문자이군요");
} else if(charCode>=48 && charCode<=57) {
System.out.println("숫자이군요");
} else {
System.out.println("다른 문자이군요");
}
}
/**
* 연습문제 : 정수 1개가 주어진다. 2와 3의 배수이면 2 또는 3의 배수이군요
* 아니면, 2 또는 3의 배수가 아니군요
*/
public void exam10(){
int value = 6;
if((value % 2 == 0) || (value % 3 == 0)){
System.out.println("2 또는 3의 배수이군요");
} else {
System.out.println("2 또는 3의 배수가 아니군요");
}
}
}
if문과 switch문
package chap04;
/**
* packageName : chap04
* fileName : Sec0401
* author : GGG
* date : 2023-09-19
* description : 조건문
* 요약 :
* if문 - if(조건문1){실행문1} else if(조건문2){실행문2} else{실행문3};
* => 조건문1 true 실행문1 실행되고 조건문2 true 실행문2 실행되고 모두 아니면 실행문3 실행
* switch문 - switch(변수) { case 값1: 실행문1;break; case 값2: 실행문2;break;
* default: 실행문3;break;
* }
* <p>
* ===========================================================
* DATE AUTHOR NOTE
* —————————————————————————————
* 2023-09-19 GGG 최초 생성
*/
public class Sec0401 {
/**
* 예제 1 : 초기값이 90이상이면 점수가 90보다 큽니다.
* 등급은 A입니다. 출력
* 90이하이면 점수가 90보다 작습니다.
* 등급은 B입니다. 출력
*/
public void exam01(){
int score = 93; // 초기값
if(score >= 90){
System.out.println("점수가 90보다 큽니다.");
System.out.println("등급은 A입니다.");
} else {
System.out.println("점수가 90보다 작습니다.");
System.out.println("등급은 B입니다.");
}
}
/**
* 자바 랜덤 함수 소개하는 예제
* 랜덤 함수 : Math.random() : 0 ~ 1 사이의 숫자(실수)를 내보내기(retrun)
* 1 ~ 10 까지의 정수를 뽑기
* 가공 :
* 1 <= x < 11 의 정수 뽑기로 변환
* 1) 0.0 <= Math.random() < 1.0
* 2) 0.0 * 10 <= Math.random() * 10 < 1.0 * 10 // 10 곱하기
* 3) (int)0.0 * 10 <= (int)Math.random() * 10 < (int)1.0 * 10 // 강제 형변환 : 실수 -> 정수
* => 0 <= (int)Math.random() * 10 < 10
* 4) 0 + 1 <= (int)Math.random() * 10 + 1 < 10 + 1
* => 1 <= (int)Math.random() * 10 + 1 < 11
*/
public void exam04(){
// 예제 : 주사위를 던져서 나오는 숫자를 화면에 출력하세요
// 단, 1 ~ 6 까지의 랜덤하게 나오는 것
int num = (int)(Math.random() * 6) + 1; // 1 ~ 10 => 1 ~ 6
// 조건문
if(num == 1){
System.out.println("1번");
} else if(num == 2){
System.out.println("2번");
} else if(num == 3){
System.out.println("3번");
} else if(num == 4){
System.out.println("4번");
} else if(num == 5){
System.out.println("5번");
} else {
System.out.println("6번");
}
}
/**
* switch 문을 이용해서 코딩하기
* 예제 : 부장이면 "700만원" 출력, 과장이면 "500만원" 출력
* 그외 "300만원" 출력
*/
public void exam08(){
String position = "과장";
switch (position){
case "부장":
System.out.println("700만원");
break;
case "과장":
System.out.println("500만원");
break;
default:
System.out.println("300만원");
}
}
}
반복문 for
package chap04;
/**
* packageName : chap04
* fileName : Sec0402
* author : GGG
* date : 2023-09-19
* description : 반복문
* 요약 :
* for문 : for(초기화식; 조건식; 증감식) {반복문;}
* => 조건식이 true 일때만 반복문이 실행됨
* while문 : 초기화식;
* while(조건식) {
* 반복문;
* 증감식;
* }
* <p>
* ===========================================================
* DATE AUTHOR NOTE
* —————————————————————————————
* 2023-09-19 GGG 최초 생성
*/
public class Sec0402 {
/**
* 예제1 : 1 ~ 10까지 숫자를 화면에 출력하세요
*/
public void exam01() {
// fori : for문 단축키
for (int i = 1; i < 11; i++) {
System.out.println(i);
}
}
/**
* 예제2 : 1 ~ 100 까지의 합
*/
public void exam02() {
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
}
System.out.println("1~100 까지의 합 : " + sum);
}
/**
* 예제 : 주사위 2 : 주사위를 던져서 나오는 숫자를 계속 화면에 출력하되 6이 나오면 반복문을 중단하고 빠져나오세요
* 단, 빠져 나올때 프로그램 종료 라고 출력하세요
*/
public void exam08() {
while (true) {
int num = (int) (Math.random() * 6) + 1;
System.out.println(num);
if (num == 6) {
break;
}
}
System.out.println("프로그램 종료");
}
/**
* 예제 : 1 ~ 10 사이의 수 중에서 짝수만 출력하는 코드 : continue
*/
public void exam09() {
for (int i = 1; i <= 10; i++) {
if (i % 2 != 0) continue;
System.out.println(i);
}
}
/**
* (참고) 새로나온 사용법 : 반복문의 라벨
* 활용 : 중첩 for문에서 주로 사용
*/
public void exam10() {
Outter:
for (char upper = 'A'; upper <= 'Z'; upper++) {
for (char lower = 'a'; lower <= 'z'; lower++) {
System.out.println(upper + "-" +lower); // 화면 출력
// g 가 나오면(안쪽/바깥쪽 모두) 반복문 중단
if(lower == 'g'){
break Outter; // 이중 중첩 반복문 탈출
}
}
}
System.out.println("프로그램 종료");
}
}
참조자료형과 참조변수
package chap05;
/**
* packageName : chap05
* fileName : Sec0501
* author : GGG
* date : 2023-09-19
* description : 참조 자료형과 참조 변수
* 요약 :
* 기본 자료형 : int(4), long(8), float(4), double, boolean 자료형
* => 스택 메모리 영역에 그대로 저장됨
* 참조 자료형 : String(문자열), 배열, 객체
* => 힙 메모리 영역에 값이 저장되고 , 스택 메모리 영역에 주소값이 저장됨
* JVM(Java Virtual Machine) : 자바 가상 머신 : jdk(자바가상머신)
* 역할 : linux / windows(운영체제) 모든 곳에서 실행할 수 있게 만드는 프로그램
* 비교연산자(==) : 기본자료형에서는 값을 비교하고,
* 참조자료형에서는 주소값을 비교하게 됨
* (스택 메모리 영역의 저장된 값을 비교함)
* null 포인트 에러(예외) : 프로그램을 강제 비정상 중단함
* <p>
* ===========================================================
* DATE AUTHOR NOTE
* —————————————————————————————
* 2023-09-19 GGG 최초 생성
*/
public class Sec0501 {
/**
* 비교연산자(==) 와 equals 함수 예제
*/
public void stringEqualExam(){
// 참조 자료형
// 참조자료형 객체변수 = new 생성자함수();
// 메모리에 랜덤한 주소(방번호)값으로 생성됨
String strVar1 = new String("신민철");
String strVar2 = new String("신민철");
// 주소값(방번호)비교 : 개발자 입장에서는 의미 없음
if(strVar1 == strVar2){
System.out.println("두개의 주소가 같음");
} else {
System.out.println("두개의 주소가 다름");
}
// equals() 함수 사용 : 값을 비교하는 함수
if(strVar1.equals(strVar2) == true){
System.out.println("두개의 값이 같음");
} else {
System.out.println("두개의 값이 다름");
}
// null 포인터 예외(에러)
// 배열에서 null 에러
int[] intArray = null; // 없음(공간 없음)
intArray[0] = 10; // 0번지 방에 10번을 넣으니 null 에러가 발생
// 객체에서 null 에러
String str = null; // 권장코딩 : String str = ""; 빈 문자열로 초기화
// 문자열의 길이를 가져오는 함수 : 문자열.length()
System.out.println("총 문자 수는 : " + str.length()); // null 에러 발생
}
}
배열
package chap05;
import java.util.Arrays;
/**
* packageName : chap05
* fileName : Sec0502
* author : GGG
* date : 2023-09-19
* description : 배열
* 요약 :
* 배열 : 같은 자료형의 데이터를 연속된 공간에 나열하고 인덱스를 부여해 놓은 자료구조
* 인덱스 : 배열 항목에 붙인 번호 , 0 ~ n 까지의 범위
* 배열 선언(정의) : 자료형[] 변수;
* 배열 생성 : 1) 자료형[] 변수 = {값1, ..., 값n};
* 2) 자료형[] 변수 = new 자료형[길이];
* 3) 자료형[] 변수 = new 자료형[길이] {값1, ... , 값n};
* 배열 길이 : 배열의 값의 개수, 배열변수.lenght (읽기전용)
* 다차원 배열 : 배열 안에 또 다른 배열이 있음
* 자료형[][] 변수 = new 자료형[크기][크기];
* 자료형[][] 변수 = {{값1...},{값1...}};
* => for문 코딩 (2개사용)
* => int[][] arr = {{1,2,3}, {4,5,6}}
* => 팁 ! : for(int i = 1; i<=2; i++){
* for(int j = 1; j <=3; j++){
* }
* }
* 향상된 for 문 : for(자료형 변수 : 배열) {} => 자동으로 인덱스 증가
* <p>
* ===========================================================
* DATE AUTHOR NOTE
* —————————————————————————————
* 2023-09-19 GGG 최초 생성
*/
public class Sec0502 {
/**
* 예제 : 학생 10명의 성적을 저장하고 평균값 구하기
*/
public void getStudent(){
// 배열의 초기값
int[] score = {83, 84, 85, 86, 87, 88, 89, 90, 91, 92};
int sum = 0; // 합계 변수
for (int i = 0; i < score.length ; i++) {
sum += score[i]; // 배열의 값 모두 더하기(누적합)
}
// 평균구하기
double avg = (double)sum / 10; // 평균
System.out.println("sum = " + sum + " , avg = " + avg);
}
/**
* 예제 2 : 배열에서 함수의 매개변수로 전달시 주의점
*/
public void arrayFunc(){
int[] scores = {84, 91, 88};
int sum2 = add(scores); // ok 가능
// 이렇게 하면 안됨
// int sum3 = add({84, 91, 88}); // 에러 발생
// 참고)
int sum4 = add(new int[]{84, 91, 88}); // 가능
System.out.println(sum2);
System.out.println(sum4);
}
// 더하기 함수 생성해서 호출해서 쓰기
public int add(int[] scores) {
int sum = 0;
for (int i = 0; i < 3; i++) {
sum += scores[i];
}
return sum;
}
/**
* 배열의 2번째 정의 방법
*/
public void arrayTwo(){
int[] arr1 = new int[3]; // 배열의 정의(선언) : 빈방을 만들기(메모리에)
// 정수 : 기본값(0), 문자열 : null, 실수 : 0.0 등
// 배열의 3가지 방에 값넣기
arr1[0] = 10;
arr1[1] = 20;
arr1[2] = 30;
// 배열 출력
for (int i = 0; i < 3; i++) {
System.out.println(arr1[i]); // 배열 값 출력
}
// TODO: 배열의 안에 값을 간단히 확인하기
// 참고
// 사용법 : Arrays.toString(배열변수)
System.out.println(Arrays.toString(arr1));
}
/**
* 얇은 복사(shallow copy) vs 깊은 복사(depp copy)
*/
public void copyArray(){
// TODO: 얇은 복사
int[] oldArray = {1, 2, 3};
int[] copyArray = oldArray; // 얇은 복사(주소값)을 복사
int[] newArray = new int[3]; // 깊은 복사용 변수
// 스택방 | 힙
// oldArray | 100 <------> 100 : {1, 2, 3}
// copyArray | 100
// TODO : 얇은 복사 특징 : oldArray 값을 변경하면 copyArray 값도 같이 변경됨
// : copyArray 값을 변경해도 원본인 oldArray 도 변경됨
// 위의 현상을 피하고자 깊은 복사를 함
// TODO : 깊은 복사 : 반복문 이용
for (int i = 0; i < newArray.length ; i++) {
newArray[i] = oldArray[i]; // 깊은 복사(원본값 바뀌어도 복사본이 바뀌지 않음)
}
}
/**
* 향상된 for문 : for(자료형 변수 : 배열) {반복문};
* 아래 점수 총합을 출력하세요
*/
public void AdvancedExam(){
int[] scores = {95, 71, 84}; // 국영수 점수 배열
int sum = 0;
for (int s : scores) {
sum += s;
}
double avg = (double)sum / scores.length;
System.out.println("점수의 총합 : " + sum + ", 점수의 평균 : " + avg);
}
}
열거형
package chap05;
import java.util.Calendar;
/**
* packageName : chap05
* fileName : Sec0503
* author : GGG
* date : 2023-09-19
* description : 열거형 사용
* 요약 :
* <p>
* ===========================================================
* DATE AUTHOR NOTE
* —————————————————————————————
* 2023-09-19 GGG 최초 생성
*/
public class Sec0503 {
/**
* 열거형 사용 예제
*/
public void EnumWeek(){
Week today = null;
// 달력 객체 : Calendar
Calendar calendar = Calendar.getInstance(); // 객체 가져오기
int week = calendar.get(Calendar.DAY_OF_WEEK); // 현재 요일(1 ~ 7 숫자)
// 조건식
switch (week){
case 1:
today = Week.SUNDAY; break;
case 2:
today = Week.MONDAY; break;
case 3:
today = Week.TUESDAY; break;
case 4:
today = Week.WEDNESDAY; break;
case 5:
today = Week.THURSDAY; break;
case 6:
today = Week.FRIDAY; break;
case 7:
today = Week.SATURDAY; break;
}
System.out.println("오늘 요일 :" + today);
}
}
package chap05;
/**
* packageName : chap05
* fileName : Week
* author : GGG
* date : 2023-09-19
* description : 열거형 클래스
* 요약 :
* 열거 자료형 : 몇 가지로 제한된 상수를 가지는 자료형
* 사용법(정의) : enum 변수명 { 상수1, 상수2, ... 상수n }
* 클래스 내에서 사용
* 변수명.상수명 ex) Week.MONDAY
* <p>
* ===========================================================
* DATE AUTHOR NOTE
* —————————————————————————————
* 2023-09-19 GGG 최초 생성
*/
public enum Week {
// 월,화,수,목,금,토,일 정의(상수)
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
SUNDAY
}
package chap05;
import java.util.Arrays;
/**
* packageName : chap05
* fileName : Verify05
* author : GGG
* date : 2023-09-19
* description : 배열 / 열거형 연습문제
* 요약 :
* <p>
* ===========================================================
* DATE AUTHOR NOTE
* —————————————————————————————
* 2023-09-19 GGG 최초 생성
*/
public class Verify05 {
/**
* 주어진 배열에서 최대값을 구해보세요
*/
public void exam04() {
int[] array = {1, 5, 3, 8, 2};
int max = array[0];
for (int i = 0; i < array.length; i++) {
if (max < array[i]) {
max = array[i];
}
}
System.out.println(max);
}
/**
* 2) 중첩 for문을 이용해서 주어진 배열의 전체 항목의 합과 평균을 구해보세요.
*/
public void exam05() {
int[][] array = { { 95, 86 }, { 83, 92, 96 }, { 78, 83, 93, 87, 88 } };
int sum = 0;
int count = 0;
for(int i = 0; i < array.length; i++){
for(int j = 0; j < array[i].length; j++){
sum += array[i][j];
count += 1;
}
}
double avg = (double) sum / count;
System.out.println(sum);
System.out.println(avg);
}
}
-- 19_Procedure
-- pl/sql : 프로시저/펑션, DB 프로그래밍 분야(SQL 숙련자들)
-- 난이도가 높음
-- 소스 : Oracle DB에 저장됨
-- 장점 : 1) 성능향상
-- 자바/JS 처럼 코딩하는 것을 말함
-- 코딩 특징 : 1) 제어문 (조건문/반복문), 변수/상수
-- 예제1)
-- 화면 출력 모드 변경 : ON (출력 켜기)
SET SERVEROUTPUT ON;
-- 입력 : 대화상자 입력값이 변수명에 입력됨
-- 사용법 ) ACCEPT 변수명 prompt '문자열'
-- p_변수명 : 입력용 변수
-- v_변수명 : 단순 변수
ACCEPT p_num1 prompt '첫번째 숫자를 입력하세요'
ACCEPT p_num2 prompt '두번째 숫자를 입력하세요'
-- 1) 선언부 : DECLARE
DECLARE
-- 변수초기화, 변수 정의 : 숫자(NUMBER), 문자(VARCHAR2), 날짜(DATE) [자료형]
v_sum NUMBER(10);
BEGIN
-- 2) 실행부 : BEGIN
-- 프로시저 코딩 : 업무 코딩(비지니스 로직 코딩 : 실무용어)
-- 사용법) 입력값(p_num) 변수 : &변수명 사용
-- 대입연산자 - :=
-- v_sum : 선언부에서 정의한 변수
v_sum := &p_num1 + &p_num2; -- 입력값 2개를 더하기
-- 문자열 붙이기 : 문자열 || 문자열2 ...
dbms_output.put_line('총합은 : ' || v_sum); -- 화면에 1줄씩 출력하는 함수
END;
/
결과 =======================
신규:DECLARE
v_sum NUMBER(10);
BEGIN
v_sum := 10 + 20;
dbms_output.put_line('총합은 : ' || v_sum);
END;
총합은 : 30
PL/SQL 프로시저가 성공적으로 완료되었습니다.
=======================
-- 예제 2) 입력받은 사원번호에 해당하는 월급 출력하기 : EMPLOYEE
-- 입력값 : 7788 (SCOTT)
ACCEPT p_empno prompt '사원번호를 입력하세요'
-- 프로시저 코딩
DECLARE
-- 1) 선언부 : 변수 정의
v_sal NUMBER(10); -- 10자리 숫자
BEGIN
-- 2) 실행부
-- 사용법) SELECT 컬럼명 INTO 변수명 FROM 테이블명 : 컬럼의 값이 변수에 저장됨
SELECT SALARY INTO v_sal
FROM EMPLOYEE
WHERE ENO = &p_empno;
-- 3) 결과 출력 : v_sal
dbms_output.put_line('해당 사원의 월급은 : ' || v_sal);
END;
/
=== 결과
해당 사원의 월급은 : 3000
===
-- 예제 3) 조건문 : IF/ELSIF/ELSE/END IF
-- 입력값 변수 : p_num
ACCEPT p_num PROMPT '숫자를 입력하세요.'
-- DECLARE(선언부) 생략 : 변수 정의할것이 없으면 생략가능
BEGIN
-- 실행부
-- 사용법) IF 조건식 THEN
-- 실행문;
-- ELSE
-- 실행문2;
-- END IF
-- MOD(값, 나눌값) : 나머지 연산하는 함수
-- 비교연산자 : =
IF MOD(&p_num, 2) = 0 THEN
DBMS_OUTPUT.PUT_LINE('짝수입니다.'); -- 화면출력
ELSE
DBMS_OUTPUT.PUT_LINE('홀수입니다.');
END IF;
END;
/
-- 예제 4) 조건문 계속 : IF/ELSIF/ELSE/END IF;
-- 사원테이블에 사원명을 입력받아 급여가 3000 이상이면 고소득자입니다. 출력
-- 2000 이상이면 중간 소득자입니다. 출력
-- 모두 아니면 저소득자입니다. 출력
-- 입력값 변수 : p_ename
ACCEPT p_ename PROMPT '사원 이름를 입력하세요.'
-- 선언부(정의부)
DECLARE
-- 변수 2개 :
-- 대문자 변환 함수 : UPPER(문자열)
-- 대상 테이블의 컬럼의 자료형을 참조해서 변수의 자료형으로 정의함
-- 사용법) 변수명 테이블명.컬럼명%TYPE
v_ename EMPLOYEE.ENAME%TYPE := UPPER('&p_ename');
v_sal EMPLOYEE.SALARY%TYPE;
-- 실행부
BEGIN
-- 사원명을 입력받아 조회하는 SQL문 : 결과는 v_sal 변수에 저장
SELECT SALARY INTO v_sal
FROM EMPLOYEE
WHERE ENAME = v_ename;
-- 조건문
IF v_sal >= 3000 THEN
DBMS_OUTPUT.PUT_LINE('고소득자입니다.');
ELSIF v_sal >= 2000 THEN
DBMS_OUTPUT.PUT_LINE('중간 소득자입니다.');
ELSE
DBMS_OUTPUT.PUT_LINE('저소득자입니다.');
END IF;
END;
/
-- 예제 5) 반복문 : 커서
-- 입력값 변수 : p_dno
ACCEPT p_dno PROMPT '부서번호를 입력하세요.'
-- 선언부(정의부)
DECLARE
-- 커서(2차원배열) : 여러 데이터를 가지고 있는 SELECT 조회문
-- 커서 정의하는 부분
-- 사용법)
-- CURSOR 커서변수명 IS
-- SELECT 컬럼명, 컬럼명2, 컬럼명2, ...
-- FROM 테이블명
-- WHERE 조건절;
CURSOR emp_cursor IS
SELECT ENAME, SALARY, DNO
FROM EMPLOYEE
WHERE DNO = &p_dno;
-- 실행부
BEGIN
-- FOR문(반복문) == 자바/JS 향상된 FOR문과 비슷
-- 증감식 없고, 데이터의 끝에 도달하면 반복문 종료
-- 사용법) FOR 변수명(객체) IN 커서변수명(배열) LOOP
-- 반복문(변수명.컬럼명);
-- END LOOP;
FOR emp_record IN emp_cursor LOOP
-- 차례로 화면에 출력하기
DBMS_OUTPUT.PUT_LINE(emp_record.ename || ' ' || emp_record.salary
|| ' ' || emp_record.dno);
END LOOP;
END;
/
-- (참고) 실무에서 사용하는 이름있는 프로시저 형태
-- 사용법)
-- CREATE OR REPLACE PROCEDURE 프로시저명
-- (매개변수 in 자료형
-- 내보내기변수 out 자료형 -- js return 값과 비슷
-- )
-- IS
-- 선언부(정의부)
-- BEGIN
-- 실행문;
-- END;
-- /
-- 프로시저 정의 : DB에 소스가 저장됨
CREATE OR REPLACE PROCEDURE pro_ename_sal
(p_ename in employee.ename%type)
IS
-- 선언부
v_sal employee.salary%type; -- 사원테이블의 급여 자료형을 참조
-- 실행부
BEGIN
-- 사원명을 받아서 급여 조회 sql
SELECT SALARY INTO v_sal
FROM EMPLOYEE
WHERE ENAME = p_ename;
-- 화면 출력
DBMS_OUTPUT.PUT_LINE(v_sal || ' 입니다.');
END;
/
-- 프로시저 실행 (2가지)
-- 사용법) CALL 프로시저명(입력값);
-- EXEC 프로시저명(입력값);
CALL pro_ename_sal('SCOTT');
EXEC pro_ename_sal('SCOTT');
-- 예제 7) 평션 만들기
-- 예제) 부서번호를 매개변수로 받아서 위치를 출력하는 함수 정의
-- 함수(FUNCTION) 특징 : 무조건 RETURN 값이 있음(결과 내보내기가 있음)
-- 사용법)
-- CREATE OR REPLACE FUNCTION 펑션이름
-- (매개변수 in 자료형)
-- RETURN department.loc%type
-- IS
-- 선언부(정의)
-- BEGIN
-- 실행문;
-- RETURN 결과변수;
-- END;
-- /
CREATE OR REPLACE FUNCTION fn_ename_sal
(p_dno in department.dno%type)
RETURN department.loc%type
IS
-- 선언부
v_loc department.loc%type; -- 부서테이블의 위치 자료형 참조
-- 실행부
BEGIN
-- 부서번호를 매개변수로 받아 위치를 조회하는 SQL문
SELECT LOC INTO v_loc
FROM DEPARTMENT
WHERE DNO = p_dno;
RETURN v_loc;
END;
/
-- 함수 실행 : SELECT 문으로 조회
SELECT fn_ename_sal(10) FROM DUAL;
-- 18_View
-- 뷰(View) : 하나 이상의 테이블이나 다른 뷰를 이용해서 생성하는 가상의 테이블
-- 활용) 1) 보안을 유지하기 위해 사용함 : 사원테이블 - 급여컬럼(비밀로 유지 : 대외비)
-- 2) SQL 문을 미리 만들어 놓고 재활용 : 코딩 생산성 향상
VIEW 생성
-- 예제1) 부서테이블과(DEPARTMENT) 사원테이블을(EMPLOYEE)
-- 조인한 결과를 뷰로 만들어서 출력하세요
-- 뷰이름 : VW_EMP_COMPLEX
-- 열명은 중복이 안되게 지정
-- 조인
SELECT EMP.*, DEP.DNAME, DEP.LOC
FROM EMPLOYEE EMP, DEPARTMENT DEP
WHERE EMP.DNO = DEP.DNO;
-- 뷰 생성
CREATE OR REPLACE VIEW VM_EMP_COMPLEX
AS
SELECT EMP.*, DEP.DNAME, DEP.LOC
FROM EMPLOYEE EMP, DEPARTMENT DEP
WHERE EMP.DNO = DEP.DNO;
-- 뷰 사용
SELECT * FROM VM_EMP_COMPLEX;
-- 뷰 정보 확인 : 데이터사전(시스템테이블:관리용(미리생성되어 있음) : USER_VIEWS
SELECT * FROM USER_VIEWS;
-- 뷰에 INSERT 가능한가? => 가능
-- 예제 2) VW_EMP_JOB 에 INSERT 하기
-- 뷰 컬럼 : 사번, 사원이름, 부서번호, 담당업무
INSERT INTO VW_EMP_JOB
VALUES(8000, '윤정화', 30, 'SALESMAN');
COMMIT;
SELECT * FROM VW_EMP_JOB;
-- 예제3) 뷰에 그룹함수 써서 만들기
-- 그룹함수 : SUM, AVG, COUNT, MAX, MIN 등
-- 부서별(DNO) 급여합계(SUM(SALARY)), 급여평균(AVG(SALARY))을
-- 출력하는 SQL문을 뷰로 만드세요
-- 출력 : DNO, SUM(SALARY), AVG(SALARY)
-- 뷰이름 : VW_EMP_SALARY
-- 대상테이블 : EMPLOYEE
-- 힌트 : 컬럼에 별칭을 부여하세요.
-- 급여합계 : SAL_SUM
-- 급여평균 : SAL_AVG
-- 뷰 생성시 그룹함수는 별명이 필요함
CREATE OR REPLACE VIEW VW_EMP_SALARY
AS
SELECT DNO, SUM(SALARY) AS SAL_SUM, ROUND(AVG(SALARY), 1) AS SAL_AVG
FROM EMPLOYEE
GROUP BY DNO;
SELECT * FROM VW_EMP_SALARY;
-- 그룹함수로 만든 뷰에 INSERT? 불가!
-- 뷰 컬럼 : DNO, SAL_SUM, SAL_AVG
INSERT INTO VW_EMP_SALARY
VALUES(30, 1000, 3000); -- 에러발생
-- 뷰 삭제(DROP ~)
DROP VIEW VW_EMP_SALARY;
참고사항
-- (참고) 뷰 INSERT 기본 가능(그룹함수가 없을 때)
-- 뷰에 INSERT 기능 제한 : 옵션 추가 => WITH READ ONLY
-- 예제 4) WITH READ ONLY 옵션을 붙여서 뷰 만들기
-- SQL : 직위가 MANAGER 인 사원을 출력하는 뷰 만들기
CREATE OR REPLACE VIEW VW_EMP_JOB_READONLY
AS
SELECT ENO, ENAME, DNO, JOB
FROM EMPLOYEE
WHERE JOB LIKE '%MANAGER%' WITH READ ONLY;
SELECT * FROM VW_EMP_JOB_READONLY;
-- INSERT 테스트
INSERT INTO VW_EMP_JOB_READONLY
VALUES(9000, '김주현', 30, 'MANAGER');
// 오류발생
SQL 오류: ORA-42399: 읽기 전용 뷰에서는 DML 작업을 수행할 수 없습니다.
42399.0000 - "cannot perform a DML operation on a read-only view"
연습문제
-- 19_View_Exam
-- 뷰 연습문제
--— 1) 20번 부서에(DNO) 소속된 사원의 사원번호와(ENO)
-- 이름과(ENAME) 부서번호를(DNO) 출력하는
--— VIEW를 정의하시오.(VW_EMP_DNO)
-- 대상테이블 : EMPLOYEE
-- 뷰 : SQL 문을 특정 이름으로 정해놓은 가상 테이블
CREATE OR REPLACE VIEW VW_EMP_DNO
AS
SELECT ENO, ENAME, DNO
FROM EMPLOYEE
WHERE DNO = 20;
SELECT * FROM VW_EMP_DNO;
--— 2) 이미 생성되어 있는 상기 뷰에(1번뷰) 대해 급여(SALARY)
-- 역시 출력하도록 수정해서 재생성하세요
-- (VW_EMP_DNO)
-- 대상테이블 : EMPLOYEE
CREATE OR REPLACE VIEW VW_EMP_DNO
AS
SELECT ENO, ENAME, DNO, SALARY
FROM EMPLOYEE
WHERE DNO = 20;
SELECT * FROM VW_EMP_DNO;
--— 3) 생성된 뷰를 제거하세요(VW_EMP_DNO)
DROP VIEW VW_EMP_DNO;
-- 16_System_Role
-- 유저만들기(계정생성), 권한주기
-- 1) 유저만들기
-- Oracle DB 생성 : 기본관리자 => SYSYEM 계정(SYS(최고관리자) 등)
-- 예제 1) USERTEST01 유저를 만들고 암호를 pass1 라고 지정하세요.
-- 사용법) CREATE USER 계정명 IDENTIFIED BY 암호;
CREATE USER USERTEST01 IDENTIFIED BY pass1; -- User USERTEST01이(가) 생성되었습니다.
-- 예제 2) 위에서 만든 USERTEST01 유저에 접속 권한을 부여하기
-- 사용법) GRANT CREATE SESSION TO 계정명;
GRANT CREATE SESSION TO USERTEST01; -- Grant을(를) 성공했습니다.
-- 테이블 생성 권한 부여하기
-- 사용법) GRANT CREATE TABLE TO 계정명;
GRANT CREATE TABLE TO USERTEST01; -- Grant을(를) 성공했습니다.
-- 공간에 대한 권한 부여하기(무한) : 테이블(논리공간) -> 물리공간 배정(할당)
-- 사용법) GRANT UNLIMITED TABLESPACE TO 계정명;
GRANT UNLIMITED TABLESPACE TO USERTEST01; -- Grant을(를) 성공했습니다.
ROLE
-- 예제 3) 권한들의 집합 == ROLE(롤)
-- 접속 권한들의 모임 == CONNECT 롤
-- 테이블, 인덱스, 함수 등을 사용하는 권한 모임 == RESOURCE 롤
-- VIEW 생성권한이 없음
GRANT CONNECT, RESOURCE, CREATE VIEW TO USERTEST01;
-- 유저 삭제(DROP ~)
-- 사용법) DROP USER 유저명;
DROP USER USERTEST01;
계정 테스트
테스트시 상태 : 성공이 나오면 됨!
동의어(SYNONYM)
-- 2) 동의어(SYNONYM)
-- 다른 데이터베이스나 다른 계정의 테이블, 인덱스 등의 별명을 붙이는것
-- 예제)
-- 샘플테이블(SYSTEM 계정) : SAMPLETBL
-- 컬럼 : MEMO VARCHAR2(50)
CREATE TABLE SAMPLETBL(
MEMO VARCHAR2(50)
);
-- 데이터 2건 생성
INSERT INTO SAMPLETBL VALUES('오월은 푸르구나');
INSERT INTO SAMPLETBL VALUES('최선을 다합시다');
COMMIT;
SELECT * FROM SAMPLETBL;
-- SYSTEM 계정의 테이블 -> 권한 부여 : SELECT (조회권한)
-- SELECT 권한 주기
-- 사용법) GRANT SELECT ON 테이블명 TO 계정명;
GRANT SELECT ON SAMPLETBL TO SCOTT;
-- 동의어 생성 권한 : SCOTT
-- 사용법) GRANT CREATE SYNONYM TO 계정명;
GRANT CREATE SYNONYM TO SCOTT;
-----------------------------------------------------------------------------
-- 동의어 실습
-----------------------------------------------------------------------------
-- SCOTT 계정으로 접속
-- SAMPLETBL : SYSTEM 계정이 소유하고 있는 테이블
-- 사용법) SELECT * FROM 계정명.테이블명;
SELECT * FROM SAMPLETBL; -- 에러발생
SELECT * FROM SYSTEM.SAMPLETBL;
-- 위의 경우와 같이 다른 유저의 테이블 조회시 테이블명이 길어짐
-- 동의어(테이블별명) 생성
-- 사용법) CREATE SYNOYM 테이블별명 FOR 계정명.테이블명;
CREATE SYNONYM SAMPLETBL FOR SYSTEM.SAMPLETBL;
-- 조회
SELECT * FROM SAMPLETBL; -- 동의어로 조회됨
-- 동의어 삭제(DROP ~)
DROP SYNONYM SAMPLETBL;
-- 현재 증가된 시퀀스의 값을 확인 : 최초 1번은 시퀀스명.NEXTVAL 실행 후 확인가능
-- 사용법)
-- SAMPLE_SEQ.CURRVAL
SELECT SAMPLE_SEQ.CURRVAL FROM DUAL;
-- 시스템 테이블들 : 시퀀스 확인용 테이블(뷰) : 데이터사전(DICTIONARY VIEW)
SELECT SEQUENCE_NAME
,MIN_VALUE
,MAX_VALUE
,INCREMENT_BY
FROM USER_SEQUENCES;
-- 예제 2) 임시테이블에 시퀀스 INSERT 하기
-- 임시테이블(구조만 복사): 부서(DEPARTMENT) -> (복사) DEPT_TEMP
CREATE TABLE DEPT_TEMP
AS
SELECT * FROM DEPARTMENT
WHERE 1=2;
-- 조회
SELECT * FROM DEPT_TEMP;
-- 시퀀스 INSERT : 대상 컬럼 : 시퀀스명.NEXTVAL (DNO: 부서번호)
-- 시퀀스 삭제
-- 사용법 ) DROP SEQUENCE 시퀀스명
DROP SEQUENCE SAMPLE_SEQ;
-- 시퀀스 생성
CREATE SEQUENCE SAMPLE_SEQ
INCREMENT BY 10
START WITH 1; -- 생성(10씩 증가)
-- INSERT 문 정의
INSERT INTO DEPT_TEMP
VALUES(SAMPLE_SEQ.NEXTVAL, 'ACCOUNTING', 'NEW YORK');
SELECT * FROM DEPT_TEMP;
-- 영구반영
COMMIT;
인덱스
-- 2. 인덱스( INDEX )
-- 사용) 컬럼에 인덱스를 지정하여 사용함
-- 목적) 조회속도 향상을 위해 조건에 해당하는 컬럼에 인덱스를 생성(지정)함
-- 기본키(PK) : 중복방지 + NULL값 방지 + 자동인덱스 생성
-- 예제3) 사이트에서 조회시 이름검색(ENAME)이 많은데, 속도가 느리다고 한다. (EMPLOYEE)
-- 해결) ENAME 컬럼에 인덱스 생성 -> 조회속도 향상
-- 명명법) IX_테이블명_컬럼명, IDX_테이블명_컬럼명
-- 사용법) CREATE INDEX 인덱스이름 ON 테이블명(컬럼명);
CREATE INDEX IX_EMPLOYEE_ENAME ON EMPLOYEE(ENAME);
-- 속도 느린 대상 SQL문
SELECT * FROM EMPLOYEE
WHERE ENAME LIKE 'SCOTT%'; -- 이 부분이 INDEX 를 만들 곳
-- 데이터 사전 : USER_IND_COLUMNS 뷰에서 확인
SELECT INDEX_NAME, TABLE_NAME, COLUMN_NAME
FROM USER_IND_COLUMNS
WHERE TABLE_NAME IN ('EMPLOYEE','DEPARTMENT');
툴에서 확인가능
-- 인덱스 삭제하기(DROP ~)
-- 사용법) DROP INDEX 인덱스명;
DROP INDEX IX_EMPLOYEE_ENAME;
-- *인덱스를 만들어야 하는 기준
-- 1) 테이블의 행의 개수가 많을 경우(데이터 건수가 많을경우)
-- : 10만건 이상
-- 2) WHERE(조건절)에 해당 컬림이 많이 등장할 경우
-- 3) 테이블 조인의 공통컬럼으로 사용될 경우
-- 특수 인덱스
-- 1) 결합 인덱스 : 컬럼 여러개를 묶어서 한번에 인덱스로 지정
-- 예) 아래 쿼리문 조회속도가 느릴 때
SELECT * FROM DEPARTMENT
WHERE DNAME = 'SALES'
AND LOC = 'NEW YORK';
-- 결합 인덱스 만들기
-- 사용법) CREATE INDEX 인덱스명 ON 테이블명(컬럼1, 컬럼2, ...);
CREATE INDEX IX_DEPT_COM ON DEPARTMENT(DNAME, LOC);
-- 2) 함수 인덱스 : 함수에 인덱스 걸기
SELECT * FROM EMPLOYEE
WHERE SALARY = SALARY * 12;
-- 함수 인덱스(수식인덱스)
-- 사용법) CREATE INDEX 인덱스명 ON 테이블명(수식);
CREATE INDEX IX_EMP_ANNSAL ON EMPLOYEE(SALARY * 12);
-- 기타사항 : 제약조건
-- 테이블 복사 : CREATE TABLE ~ AS SELECT ~
-- 제약조건 복사안됨(제약조건 추가 생성작업 : 기본키/참조키)
-- 참고) 시스템용 테이블 또는 뷰(VIEW): DB 관리용 테이블
-- 용도) 현재 생성된 테이블의 정보, 제약조건, 크기 등을 확인하는 용도
-- 테이블 정보(제약조건) : USER_CONSTRAINTS
-- 원본테이블 제약조건 확인
SELECT TABLE_NAME, CONSTRAINT_NAME
FROM USER_CONSTRAINTS
WHERE TABLE_NAME IN ('EMPLOYEE', 'DEPARTMENT')
ORDER BY TABLE_NAME;
-- 복사본테이블 제약조건 확인
SELECT TABLE_NAME, CONSTRAINT_NAME
FROM USER_CONSTRAINTS
WHERE TABLE_NAME IN ('EMP_COPY', 'DEPT_COPY')
ORDER BY TABLE_NAME;
✔ 테이블 생성 후 제약조건 추가/변경/제거하기
-- 예제 1) 사원복사본 테이블(EMP_COPY)에 기본키(PRIMARY KEY) 추가하기
-- 사용법) ALTER TABLE 테이블명
-- ADD CONSTRAINT PK_테이블명_컬럼명 PRIMARY KEY(컬럼명);
-- ENO : 사원번호에 기본키 추가
ALTER TABLE EMP_COPY
ADD CONSTRAINT PK_EMP_COPY_ENO PRIMARY KEY(ENO);
-- 예제2) 부서복사본(DEPT_COPY) 테이블에 기본키(PK) 추가하기
-- 기본키 : DNO(부서번호),(테이블의 데이터 중에서 유일한 값을 가져야 되는것)
ALTER TABLE DEPT_COPY
ADD CONSTRAINT PK_DEPT_COPY_DNO PRIMARY KEY(DNO);
-- 예제3) 테이블 생성 후에 외래키(참조키:FK) 추가하기 : EMP_COPY
-- 자식테이블에 추가 (부서테이블(부모): DEPT_COPY, 사원테이블(자식): EMP_COPY )
ALTER TABLE EMP_COPY
ADD CONSTRAINT FK_EMP_COPY_DNO
FOREIGN KEY(DNO) REFERENCES DEPT_COPY(DNO);
-- 예제4) 테이블 생성 후에 제약조건 삭제하기
-- 부모테이블(부서: 부서번호)의 기본키 <-> 자식테이블의 참조키(사원: 부서번호)
-- 부모테이블의 기본키 삭제하기 : 강제삭제하기 옵션(CASCADE)
-- CASCADE : 자식테이블에 있는 외래키도 같이 삭제됨
ALTER TABLE DEPT_COPY
DROP PRIMARY KEY; -- 자식테이블에 참조키가 걸려있으면 오류발생
ALTER TABLE DEPT_COPY
DROP PRIMARY KEY CASCADE;
-- 예제5) 제약조건 변경하기
-- EMP_COPY(사원) : ENAME (NULL 허용) -> ENAME NOT NULL 제약조건으로 변경
ALTER TABLE EMP_COPY
MODIFY ENAME CONSTRAINT NN_EMP_COPY_ENAME NOT NULL;
-- 제약조건이름으로 제약조건 삭제하기
ALTER TABLE EMP_COPY
DROP CONSTRAINT NN_EMP_COPY_ENAME;
✔ 연습문제
-- 13_Table_Constraint_Exam
-- 제약조건 연습문제
--— 1) EMPLOYEE 테이블의 구조를 복사하여 EMP_SAMPLE 란
-- 이름의 테이블을 만드시오.
--— 사원 테이블의 사원번호 컬럼(ENO)에
-- 테이블 레벨로 PRIMARY KEY 제약조건을 지정하되,
--— 제약 조건 이름은 PK_MY_EMP 하시오.
-- 1) 복사본 : 제약조건 복사 안됨(기본키,외래키 직접 생성해야 함)
-- 테이블 구조복사
CREATE TABLE EMP_SAMPLE
AS
SELECT * FROM EMPLOYEE
WHERE 1=2;
-- ENO에 PRIMARY KEY 제약조건 지정
ALTER TABLE EMP_SAMPLE
ADD CONSTRAINT PK_MY_EMP PRIMARY KEY(ENO);
--— 2) DEPARTMENT 테이블의 구조를 복사하여
-- DEPT_SAMPLE란 이름의 테이블을 만드시오.
--— 부서번호 컬럼(DNO)에 PRIMARY KEY 제약조건을 지정하되,
--— 제약 조건 이름은 PK_MY_DEPT 하시오.
-- 테이블 구조복사
CREATE TABLE DEPT_SAMPLE
AS
SELECT * FROM DEPARTMENT
WHERE 1=2;
-- DNO에 PRIMARY KEY 제약조건 지정
ALTER TABLE DEPT_SAMPLE
ADD CONSTRAINT PK_MY_DEPT PRIMARY KEY(DNO);
--— 3) 사원 테이블의(EMP_SAMPLE) 부서번호 컬럼에 존재하지 않는
-- 부서의 사원이 배정되지 않도록
--— 외래 키(FOREIGN KEY:FK) 제약조건을 지정하되,
-- FK_MY_DEPT_EMP 로 하시오.
--— 참조테이블 : DEPARTMENT (데이터가 있음)
--— 참조키,외래키(FOREIGN KEY:FK)
-- DNO 컬럼에 외래키 지정
ALTER TABLE EMP_SAMPLE
ADD CONSTRAINT FK_MY_DEPT_EMP
FOREIGN KEY(DNO) REFERENCES DEPARTMENT(DNO);
SELECT TABLE_NAME, CONSTRAINT_NAME
FROM USER_CONSTRAINTS
WHERE TABLE_NAME IN ('EMP_SAMPLE', 'DEPT_SAMPLE')
ORDER BY TABLE_NAME;
-- 07_Subquery
-- 서브쿼리 : 단일행 서브쿼리(1건만 나옴)
-- 부등호나 등호를 사용하여 비교함
-- 예제 1) SCOTT 사원보다 급여를 많이 받는 사원을 찾기위한 SQL문을 작성하세요
-- 해결 1-1) 사원테이블에서 SCOTT 사원의 급여를 찾은 후에 (1번)
-- 해결 1-2) 그 급여를 비교해서 많이 받는 사원을 추가로 찾아야함 (2번)
-- 1번
SELECT SALARY
FROM EMPLOYEE
WHERE ENAME = 'SCOTT'; -- 3000(급여)
-- 2번
SELECT ENAME, SALARY
FROM EMPLOYEE
WHERE SALARY > 3000;
-- 문제점 : 성능저하 : 여러번 쿼리로 인해
-- WHERE 절의 컬럼과 서브쿼리의 SELECT 컬럼이 동일해야함
-- 사용법
-- SELECT 컬럼명 FROM 테이블명
-- WHERE 비교컬럼 > (SELECT 비교컬럼 FROM 테이블명);
SELECT ENAME, SALARY
FROM EMPLOYEE
WHERE SALARY > (SELECT SALARY
FROM EMPLOYEE
WHERE ENAME = 'SCOTT');
-- 예제1 : SCOTT 사원과 동일한 부서에서 DNO 근무하는 사원 구하기
SELECT ENAME
FROM EMPLOYEE
WHERE DNO = (SELECT DNO
FROM EMPLOYEE
WHERE ENAME = 'SCOTT');
-- 예제2 : 30번 부서에서 최소급여를 구한후 그 최소 급여보다 부서별 최소 급여가 큰 부서만 출력하세요
SELECT MIN(SALARY)
FROM EMPLOYEE
WHERE DNO = 30;
SELECT DNO, MIN(SALARY)
FROM EMPLOYEE
GROUP BY DNO
HAVING MIN(SALARY) > (SELECT MIN(SALARY)
FROM EMPLOYEE
WHERE DNO = 30);
-- 3) 특수한 경우 아래처럼 사용도 가능함
-- SELECT 문 안에도 들어감
SELECT 2*3, (SELECT 4*3 FROM DUAL)
FROM DUAL;
-- FROM 문 안에도 들어감
SELECT EMP.ENAME, EMP.ENO
FROM (SELECT ENAME, ENO FROM EMPLOYEE) EMP;
-- 2) 다중 행 서브쿼리(자식쿼리) : 여러 건이 나옴
-- 예제 4) (1) 부서별 최소급여를 받는 사원 중에서 (2) 사원번호와 이름을 출력하세요
-- (1) 부서별 최소급여 받는 사원 출력
SELECT MIN(SALARY)
FROM EMPLOYEE
GROUP BY DNO;
-- (2) 950, 1300, 800 급여를 받는 사원번호와 이름 출력
SELECT ENO, ENAME
FROM EMPLOYEE
WHERE SALARY IN (950, 1300, 800);
-- 최종쿼리
SELECT ENO, ENAME
FROM EMPLOYEE
WHERE SALARY IN (SELECT MIN(SALARY)
FROM EMPLOYEE
GROUP BY DNO);