Search

2016년 4월 16일 토요일

[Database] [Oracle] dual 테이블 사용 및 system 테이블 조회하기.

* ORACLE Database에서 Table정보 없이 기본 SELECT를 구현하려면 아래와 같이 해야한다.

SELECT 'OskarDevelopers' FROM dual;



* DB에 있는 Table, Column, View 정보 보기.

-- Table
SELECT * FROM all_tables;

-- Column
SELECT * FROM all_tab_columns;

-- View
SELECT * FROM all_views;


[Database] [DB2] dummy 테이블 사용 및 system 테이블 조회하기.

* DB2에서 Table정보 없이 기본 SELECT를 구현하려면 아래와 같이 해야한다.

SELECT 'OskarDevelopers' FROM sysibm.sysdummy1;


* DB에 있는 Table, Column, View 정보 보기.

-- Table
SELECT * FROM syscat.tables;

-- Column
SELECT * FROM syscat.columns;

-- View
SELECT * FROM sysibm.sysviews;


[Database] [H2] [Java] Imbedded Database H2를 eclipse에서 사용하기.

#1. 들어가기
 앱을 개발 한다던가, 소규모의 프로젝트에서 간단하게 데이터베이스와 SQL 기능이 필요할 때,  도움이 될만한 데이터베이스를 소개하고자 한다. Imbedded Database나 H2에 관한 상세한 내용은 검색해보면 많이 나오니.. 찾아볼 것을 추천한다. 여기에서는 최초 Hello World를 찍듯, 이클립스로 "아~ 이렇게 사용하는구나" 하는 수준에서 알아본다.

#2. 준비
 1) H2 database 다운로드.
 http://www.h2database.com/html/main.html
 위 사이트에 들어가보면, All Platforms 라고 된 zip 파일을 다운받으면 된다. (만약, Java와 eclipse없이 H2만을 편하게 사용하려면, http://www.h2database.com/html/quickstart.html를 참조해 그냥 사용하면 된다. )























 2) zip파일의 압축을 풀면 bin 폴더에 h2-1.4.191.jar 파일이 있다.
  (버젼은 다운로드 시점에 따라 다를 수 있다.)









 3) eclipse에서 Java Project 생성 후, lib폴더를 만들어(정리정돈을 위해..) 복사해 넣어주자.











 4) h2-1.4.191.jar을 선택해 마우스 우클릭 ->  Build Path -> Add to Build Path.
 여기까지 된 상태면, H2 데이터베이스 사용을 위한 모든 준비가 끝났다고 봐도 좋다. (참 간단하죠??)











#3. 사용하기
 아주아주 간단하게 필요한 것만 구현한 코드를 아래에서 살펴보자.
1) 14~16번 줄에서 새로 만들 DB와 USER, PW를 설정.
2) 만약 프로그램을 실행시킬 때마다 DB를 Drop 시키지 않고 계속 유지하고 싶다면, 20번 줄은 주석처리.
3) 50~60번 줄을 통해 간단하게 테이블을 생성해 데이터를 넣고, 조회하는 것을 테스트 해봤다.
4) 참고로 H2는 왠만한 SQL문법들은 다 사용할 수 있다. (참조 : http://www.h2database.com/html/grammar.html)













package kr.oskarDevelopers.martin;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import org.h2.tools.DeleteDbFiles;

public class TestDriver {

    private static final String DB_DRIVER = "org.h2.Driver";
    private static final String DB_CONNECTION = "jdbc:h2:~/testdb"; // database name
    private static final String DB_USER = "martin";                 // user id
    private static final String DB_PASSWORD = "1234";               // passward

    public static void main(String[] args) {
        try {
            DeleteDbFiles.execute("~", "testdb", true); // drop db if exist 'testdb'
            initDB();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    private static Connection getDBConnection() {
        Connection dbConnection = null;
        try {
            Class.forName(DB_DRIVER);
        } catch (ClassNotFoundException e) {
            System.out.println(e.getMessage());
        }
        try {
            dbConnection = DriverManager.getConnection(DB_CONNECTION, DB_USER, DB_PASSWORD);
            return dbConnection;
        } catch (SQLException e) {
            System.out.println(e.getMessage());
        }
        return dbConnection;
    }

    private static void initDB() throws SQLException {
        Connection connection = getDBConnection();
        Statement stmt = null;
        try {
            connection.setAutoCommit(false);
            stmt = connection.createStatement();

            // create TEST_TABLE for example
            stmt.execute("CREATE TABLE TEST_TABLE(idx INT PRIMARY KEY, name VARCHAR(100));");
            
            // insert some values into TEST_TABLE
            stmt.execute("INSERT INTO TEST_TABLE VALUES(1, 'Martin.Park'), (2, 'OskarDevelopers');");
             
            // get result by using SELECT query
            ResultSet rs = stmt.executeQuery("SELECT * FROM TEST_TABLE;");
            while (rs.next()) {
                System.out.println("idx : " + rs.getString("idx") + " / " + "name : " + rs.getString("name"));
            }
            
            stmt.close();
            connection.commit();
            
        } catch (SQLException e) {
            System.out.println("Exception Message " + e.getLocalizedMessage());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            connection.close();
        }
    }
}


#4. 결과화면
 이제부터는 사용 목적에 맞게 이용하면 된다.  (너무 성의없나?..)











2016년 4월 2일 토요일

[Algorithm] [JAVA] 재귀함수 - 하노이의 탑 구현해보기.

#1. 들어가기
 알고리즘을 공부하다보면, 재귀함수가 단골손님으로 등장한다. 간단하게 말하면 자기 자신을 다시 호출하는 것이 재귀함수인데, 보통 잘 알려진 것이 하노이의 탑이다.
 하지만, 처음 알고리즘을 배우는 사람들은 "아, 그런가보다~" 하고 말지, 하노이의 탑을 어떻게 구현 해야할지는 막막하다.
 지금부터 간단하게 하노이의 탑을 살펴보고, 자바로 하노이의 탑을 구현해보자.


#2. 하노이의 탑?
 * 하노이의 탑에 대해서 자세하게 알고 싶으면 인터넷 검색을 추천한다.























 알고리즘 구현에 앞서, 간단하게 큰 특징을 정리해보면 다음과 같다.
1) 탑을 구성하는 원판은 번호(혹은 크기)가 모두 다르다.
2) 항상 번호(혹은 크기)가 큰것이 아래로 가야한다.
3) 쌓여있는 탑을 다른 기둥으로 똑같이 쌓아야 하며, 움직일 수 있는 원판은 한 번에 하나씩만 가능하다.
4) 원판을 움직일 때, 각 기둥의 가장 위에 위치한 원판만 가능하다.
5) 움직이려는 원판을 다시 내려놓을 때, 자신의 번호(혹은 크기)가 놓으려는 원판보다 작아야 한다.


#3. Java로 구현하기
 코딩을 하는 사람마다 구현하는 방법은 각자 다르겠지만, 여기서 사용한 방법은 다음과 같다. 아래의 그림처럼 먼저 클래스를 2개로 나누었고, Hanoi 클래스에서 알고리즘의 구현을 했고, Driver 클래스에서 실행을 한다.












1) Hanoi 클래스
매소드 중에 moveTower 부분을 자세히 살펴보면, 재귀함수가 사용됨을 알 수 있다.
lastMovedLine 의 숫자를 1 혹은 2로 바꿔서, 하노이 탑의 최종 위치를 변경할 수 있다. 
(구지 하노이의 탑을 항상 3번째 기둥으로 옮기고자 한다면, 하노이 탑이 짝수일 경우에 lastMovedLine을 2로 해주는 로직을 추가하면 된다.)


package hanoiTower;

public class Hanoi {

 private int x = 3; // fixed. A number of pillar.
 private int y = -1; // height
 private int[][] hanoiField;
 private int[] cntLine = new int[x];
 private int lastFoundLine = -1;
 private int lastMovedLine = 1; // choose the place to move. (1 or 2)
 private int moveCNT = -1; // moved times count

 public Hanoi(int num) {
  this.y = num;
  this.hanoiField = new int[num][x];
 }

 public void initHanoiTower() {
  System.out.println("Start!");
  System.out.println("==========" + "\n");

  // make HanoiTower
  for (int i = y; i > 0; i--) {
   hanoiField[i - 1][0] = i;
  }

  moveTower(y);

  System.out.println("==========");
  System.out.println("Done!");
  System.out.println("Total moved count : " + moveCNT);
 }

 public void showTower() {
  for (int i = 0; i < y; i++) {
   for (int j = 0; j < x; j++) {
    String s = String.valueOf(hanoiField[i][j]);
    if (s.length() == 1 || s.equals("0")) {
     System.out.print("| " + s.replace("0", " ")
       + blank(s.length()));
    } else {
     System.out.print("| " + s + blank(s.length()));
    }
   }
   System.out.print("|");
   System.out.println();
  }
  System.out.println("----------------" + "\n");
  moveCNT++;
 }

 public int countLine(int num) {
  for (int i = 0; i < x; i++) {
   int cnt = 0;
   for (int j = 0; j < y; j++) {
    if (hanoiField[j][i] != 0) {
     cnt = cnt + 1;
    }
   }
   cntLine[i] = cnt;
  }
  return cntLine[num];
 }

 public int[] findNumPlace(int num) {
  int[] coordinate = new int[2];
  coordinate[0] = -1;
  coordinate[1] = -1;
  for (int i = 0; i < y; i++) {
   for (int j = 0; j < x; j++) {
    if (hanoiField[i][j] == num) {
     lastFoundLine = j;
     coordinate[0] = j;
     coordinate[1] = i;
    }
   }
  }
  return coordinate;
 }

 public void moveTower(int num) {
  int to = -1;
  if (num <= 2) {
   showTower();

   // move 1, 2
   for (int i = 1; i <= 2; i++) {
    hanoiField[findNumPlace(i)[1]][findNumPlace(i)[0]] = 0;
    to = x - (lastFoundLine + lastMovedLine);
    hanoiField[(y - 1) - countLine(to)][to] = i;
    lastMovedLine = to;
    showTower();
   }

   // move 1 again
   hanoiField[findNumPlace(1)[1]][findNumPlace(1)[0]] = 0;
   hanoiField[(y - 1) - countLine(to)][to] = 1;
   showTower();

  } else {
   // reflexive
   moveTower(num - 1);

   // move the tower's number bigger than 2
   hanoiField[findNumPlace(num)[1]][findNumPlace(num)[0]] = 0;
   to = x - (lastFoundLine + lastMovedLine);
   hanoiField[(y - 1) - countLine(to)][to] = num;
   lastMovedLine = to;

   // shift place when the tower's number is even.
   if (num % 2 == 0) {
    // System.out.println("!!!!!");
    lastMovedLine = lastFoundLine;
   }

   // move 1, 2 again
   moveTower(num - 1);
  }
 }

 public String blank(int num) {
  String s = String.valueOf(this.y);
  int l = s.length();
  String o = " ";
  for (int i = l - num; i > 0; i--) {
   o = o + " ";
  }
  return o;
 }
}



2) Driver 클래스
7번 라인 Hanoi()안의 숫자를 변경하면, 하노이 탑의 크기를 변경해서 볼 수 있도록 해두었다.  


package hanoiTower;

public class Driver {

 public static void main(String[] args) {
  
  // You can change the start height of HanoiTower.
  Hanoi h = new Hanoi(5);
  h.initHanoiTower();
 }
}



#4. 결과 화면
 하노이 탑을 설명할 때 사용한 이미지와 동일하게 원판을 하나하나 움직여서 탑을 우측으로 옮긴 모습을 확인할 수 있다. 






































 만약, 15개 짜리 하노이의 탑이라면? 직접 프로그램으로 돌려보길 바란다.
(혹은 운이 좋다면, 정확하게 32,767회의 움직임 끝에 하노이 탑을 모두 옮길 수 있을 것이다.)