[Info]Tags categorized posts and contents patterns..

[AJAX] Ajax Code E xamples.. [Book] About the book.. [CSS] CSS Code E xamples.. [DB] Sql Code E xamples.. [DEV] All development stor...

레이블이 odbc인 게시물을 표시합니다. 모든 게시물 표시
레이블이 odbc인 게시물을 표시합니다. 모든 게시물 표시

2016년 2월 23일 화요일

[DB]ODBC Access Driver 사용시에 Inner Join에 대한 "쿼리식의 연산자가 없는 구문 오류입니다." 오류..

출처 : Outsider's Dev Story https://blog.outsider.ne.kr/

Access(.mdb)를 사용하기 위해서 ODBC로 등록해서 JDBC로 연결할 때 평소하던 것 처럼 쿼리문을 짰는데 오류가 떨어졌다. 쿼리상으로는 문제가 없는데 Access Driver가 해당 쿼리에 대해서 지원을 하지 않는 것으로 보였다.

java.sql.SQLException: [Microsoft][ODBC Microsoft Access Driver] 'b.categoryid=a.categoryid INNER JOIN role AS c ON b.roleid=c.roleid' 쿼리식의 연산자가 없는 구문 오류입니다.

아래와 같은 쿼리이다.

SELECT a.title, b.sid, b.points, b.pattern, b.base, c.rolename
FROM itembank AS b
INNER JOIN category AS a
ON b.categoryid=a.categoryid
INNER JOIN role AS c
ON b.roleid=c.roleid
WHERE a.parent=?

INNER JOIN이 1개만 있을때는 오류가 없는데 INNER JOIN을 2번하면 오류가 나오는데 ODBC 드라이버가 그런건지 몰라도 FROM절에서 INNER JOIN을 제대로 인식하지 못하는 것 같다. 그래서 다음과 같이 괄호로 묶어 주어야 한다.

SELECT a.title, b.sid, b.points, b.pattern, b.base, c.rolename
FROM (itembank AS b
INNER JOIN category AS a
ON b.categoryid=a.categoryid)
INNER JOIN role AS c
ON b.roleid=c.roleid
WHERE a.parent=?

만약 INNER JOIN이 하나 더 붙으면 괄호를 또 감싸주어야 한다.

하튼 왜 디비를 MDB를 쓴다고 결정해놔서 이 고생을... ㅡ..ㅡ

[DB]JDBC와 ODBC로 Java에서 MS Access(.mdb) 연결하기..

출처 : Outsider's Dev Story https://blog.outsider.ne.kr/

MDB를 별로 좋아하지는 않지만 상황에 따라서 솔직히 편할때가 있는 것도 사실이고 뭐 MDB로 해야된다는데 어쩌랴... Java에서 MDB를 연결해야 하는데 알아보니 여러가지가 방법이 있었는데 여기서는 윈도우즈에서 제공하는 ODBC를 이용해서 연결하는 방법을 사용한다.(윈도우즈서버에서만 가능하다는 얘기다.)

[제어판] - [관리도구] - [데이터 원본 (ODBC)]에 들어간다.

사용자 삽입 이미지

"시스템 DSN"탬에서 새로운 ODBC를 연결하기 위해서 추가버튼을 누른다.

사용자 삽입 이미지

여기서는 MDB를 사용할 것이므로 mdb용 드라이벌를 선택한다.

사용자 삽입 이미지

데이터 원본 이름에 원하는 디비의 이름을 넣고 이제 MDB를 연결하기 위해서 데이터베이스의 "선택"을 눌러서 들어간다.

사용자 삽입 이미지

사용할 MDB를 찾아서 지정하고 이제 다시 ODBC Microsoft Access 설정화면에서 "고급"을 눌러서 들어간다.

사용자 삽입 이미지

사용할 로그인 아이디와 비밀번호를 지정한다. 이렇게 하면 ODBC의 등록과정이 완료된다.


이제 자바쪽에서 JDBC를 이용해서 연결할 차례다.
Java

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

public class DBConnection {    
    private String DB_URL = "Jdbc:Odbc:Testdata";
    private String DB_USER = "test";
    private String DB_PASSWORD= "test";
    
    Connection conn = null;
    
    public Connection getConnection() {
        try {
            Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
        } catch (ClassNotFoundException e1) {
            e1.printStackTrace();
        }
        
        try {
            Properties props = new Properties();
            props.put("charSet", "8859_1" ); 
            props.put("user", DB_USER);
            props.put("password", DB_PASSWORD);

            conn = DriverManager.getConnection(DB_URL, props);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return conn;
    }
}

여기서는 연결을 위한 설명이라서 연결부분의 코드만 가져왔다. disconnect를 예제소스에서 뺐다는 말이다.

jdbc 연결 URL로는 "Jdbc:Odbc:데이터원본이름"을 사용하고 username과 password는 ODBC등록할 때 사용한 것을 적는다.(근데 없어도 잘 돌아가는것 같다.. ㅡ..ㅡ) 드라이버 클래스는 "sun.jdbc.odbc.JdbcOdbcDriver"를 사용한다.

그리고 여기서는 Properties를 사용하였는데 이건 mdb의 한글문제때문이다. mdb는 한글을 8859_1로 사용하기 때문에 한글을 안깨지고 받아오기 위해서는 Connection을 연결할 때 charSet을 8859_1로 설정해 주어야 한다.
Java

DBConnection dbConn = new DBConnection();
Connection conn = null; 
PreparedStatement psmt = null;
ResultSet rs = null;
    
try{        
    String sql = " SELECT username FROM member ";
    conn = dbConn.getConnection();  
    psmt = conn.prepareStatement(sql);        
    
    rs = psmt.executeQuery();
            
    while (rs.next()) {
        String username = new String(rs.getString("username").getBytes("8859_1"), "euc-kr");
    }  
}catch(Exception e){
    e.printStackTrace();
}finally{
    dbConn.disConnection(rs,psmt, conn);
}

이제 Connection을 사용해서 Select 쿼리를 날리는 부분이다. import등의 필요없는 부분은 빼버렸다. 결과적으로는 14번째 라인만 보면 된다. 영문이나 숫자는 괜찮지만 한글의 경우 디비커넥션에서 사용할 때 Access에서 한글을 8859_1(ISO-8859-1)을 사용했기 때문에 여기서도 받아온 스트링을 14번 라인처럼 엔코딩을 변경해 주어야 받아온 한글이 깨지지 않고 표시된다.
(특이하게도 문서의 encoding이 euc-kr이든 utf-8이든 동일하게 위처럼 euc-kr로 인코딩을 해주어야 한글이 깨지지 않는다.)

INSERT나 UPDATE등 자바쪽에서 mdb로 한글을 넣을때도 동일하게 인코딩 타입을 변경해서 넣어주어야 한다. 당연히 인코딩은 반대로 해서...

String str = new String("한글".getBytes("euc-kr"), "ISO-8859-1");

위처럼 하면 된다. ( ISO-8859-1와 8859_1는 동인한 인코딩이다.)

디비를 mdb를 쓰면 한글을 넣고 빼는 일은 빈번할테니까 위 2가지를 메서드로 따로 만들어두면 편할것이다. (뭐 일일이 인코딩을 바꿔주면서 넣는걸 편하다고 할 수는 없지만... ㅡ..ㅡ)