사용자 도구

사이트 도구


kb:odbc

차이

문서의 선택한 두 판 사이의 차이를 보여줍니다.

차이 보기로 링크

kb:odbc [2014/11/08 16:11] (현재)
줄 1: 줄 1:
 +====== ODBC ======
 +윈도우즈계에서의 데이터베이스 접근을 위한 표준 인터페이스. [[SqlServer]] 같이 네이티브 API를 제공하지 않는 DBMS의 경우에는 [[ODBC]]를 사용해야한다. 그런데 API도 지저분하고,​ 설명도 난잡하고,​ 여러 모로 짜증 좀 나네...
 +
 +
 +====== Tips ======
 +===== 각종 핸들 속성 정리 =====
 +MSDN이 보기 어렵게 되어 있어, 따로 정리했다. 근데 뭔가 모르는 것들이 잔뜩 있네.
 +
 +==== Environment ====
 +[[http://​msdn.microsoft.com/​library/​default.asp?​url=/​library/​en-us/​odbc/​htm/​odbcsqlsetenvattr.asp | SQLSetEnvAttr]]
 +
 +^ 속성 ^ 타입 ^ 가능한 값 ^ 의미 ^
 +| SQL_ATTR_CONNECTION_POOLING | UINT | SQL_CP_OFF \\ SQL_CP_ONE_PER_DRIVER \\ SQL_CP_ONE_PER_HENV \\  | 커넥션 풀링 on/off |
 +| SQL_ATTR_CP_MATCH | UINT | SQL_CP_STRICT_MATCH \\ SQL_CP_RELAXED_MATCH | 커넥션 풀링 설정 |
 +| SQL_ATTR_ODBC_VERSION | UINT | SQL_OV_ODBC3 \\ SQL_OV_ODBC2 | 드라이버 설정 |
 +| SQL_ATTR_OUTPUT_NTS | UINT | SQL_TRUE \\ SQL_FALSE | 문자열 취급 방법 설정 |
 +
 +==== Connection ====
 +[[http://​msdn.microsoft.com/​library/​en-us/​odbc/​htm/​odbcsqlsetconnectattr.asp | SQLSetConnectAttr]]
 +
 +^ 속성 ^ 타입 ^ 가능한 값 ^ 의미 ^ 설정 가능 시점 ^
 +| SQL_ATTR_ACCESS_MODE | UINT | SQL_MODE_READ_ONLY \\ SQL_MODE_READ_WRITE | 읽기, 쓰기 | Either |
 +| SQL_ATTR_ASYNC_ENABLE | UINT | SQL_ASYNC_ENABLE_OFF \\ SQL_ASYNC_ENABLE_ON | 비동기 모드 | Either |
 +| SQL_ATTR_AUTOCOMMIT | UINT | SQL_AUTOCOMMIT_OFF \\ SQL_AUTOCOMMIT_ON | 자동 커밋 | Either |
 +| SQL_ATTR_CONNECTION_DEAD | UINT | SQL_CD_TRUE \\ SQL_CD_FALSE | 커넥션 ALIVE 여부 | After |
 +| SQL_ATTR_CONNECTION_TIMEOUT | UINT | 초 | 쿼리 후 기다릴 시간, 0 == INFINITE | Either |
 +| SQL_ATTR_CURRENT_CATALOG | STRING | 데이터베이스 이름 | 현재 작업 중인 데이터베이스 | Either |
 +| SQL_ATTR_LOGIN_TIMEOUT | UINT | 초 | 로그인 성공/​실패때까지 기다릴 시간, 0 == INFINITE | Before |
 +| SQL_ATTR_METADATA_ID | UINT | SQL_TRUE \\ SQL_FALSE | 대소문자 구별. 이외에도 뭔가 있다. | Either |
 +| SQL_ATTR_ODBC_CURSORS | UINT | SQL_CUR_USE_IF_NEEDED \\ SQL_CUR_USE_ODBC \\ SQL_CUR_USE_DRIVER | 커서 종류 설정 | Before |
 +| SQL_ATTR_PACKET_SIZE | UINT | 바이트 크기 | 네트워크를 통해 오가는 패킷 크기 | Before |
 +| SQL_ATTR_QUIET_MODE | UINT | 32비트 윈도우 핸들 | NULL이면 대화창 표시하지 않는다. | Either |
 +| SQL_ATTR_TRACE | UINT | SQL_OPT_TRACE_OFF \\ SQL_OPT_TRACE_ON | 트레이스 여부 | Either |
 +| SQL_ATTR_TRACEFILE | STRING | 파일 이름 | 트레이스 파일 이름 | Either |
 +| SQL_ATTR_TRANSLATE_LIB | STRING | 파일 이름 | 아 몰라 | After |
 +| SQL_ATTR_TRANSLATE_OPTION | UINT | 32비트 플래그 | 아 몰라 | After |
 +| SQL_ATTR_TXN_ISOLATION | UINT | 32비트 비트 마스크. SQL_TXN_ISOLATION_OPTIONS 참고 | 트랜잭션 락 레벨 | Either |
 +
 +==== Statement ====
 +[[http://​msdn.microsoft.com/​library/​en-us/​odbc/​htm/​odbcsqlsetstmtattr.asp | SQLSetStmtAttr]]
 +
 +^ 속성 ^ 타입 ^ 가능한 값 ^ 의미 ^
 +| SQL_ATTR_APP_PARAM_DESC | UINT | APD에 대한 핸들, SQL_NULL_DESC | APD가 뭐지? |
 +| SQL_ATTR_APP_ROW_DESC | UINT | ARD에 대한 핸들, SQL_NULL_DESC | ARD가 뭐지? |
 +| SQL_ATTR_ASYNC_ENABLE | UINT | SQL_ASYNC_ENABLE_OFF \\ SQL_ASYNC_ENABLE_ON | 비동기 처리 설정 |
 +| SQL_ATTR_CONCURRENCY | UINT | SQL_CONCUR_READ_ONLY \\ SQL_CONCUR_LOCK \\ SQL_CONCUR_ROWVER \\ SQL_CONCUR_VALUES \\  | 락 설정 |
 +| SQL_ATTR_CURSOR_SCROLLABLE | UINT | SQL_NONSCROLLABLE \\ SQL_SCROLLABLE | 커서 스크롤 설정 |
 +| SQL_ATTR_CURSOR_SENSITIVITY | UINT | SQL_UNSPECIFIED \\ SQL_INSENSITIVE \\ SQL_SENSITIVE | 결과를 다른 커서와 공유하는가?​ |
 +| SQL_ATTR_CURSOR_TYPE | UINT | SQL_CURSOR_FORWARD_ONLY \\ SQL_CURSOR_STATIC \\ SQL_CURSOR_KEYSET_DRIVEN \\ SQL_CURSOR_DYNAMIC ​ | 커서 종류 설정 |
 +| SQL_ATTR_ENABLE_AUTO_IPD | UINT | SQL_FALSE \\ SQL_TRUE | ? |
 +| SQL_ATTR_FETCH_BOOKMARK_PTR | UINT | 포인터 | 이진 북마크에 대한 값이라는데,​ 이건 또 뭐지? |
 +| SQL_ATTR_IMP_PARAM_DESC | UINT | IPD에 대한 핸들 | IPD가 뭐지? |
 +| SQL_ATTR_IMP_ROW_DESC | UINT | IRD에 대한 핸들 | IRD가 뭐지? |
 +| SQL_ATTR_KEYSET_SIZE | UINT | 행의 수 | 키셋 기반 커서에서 다룰 행의 수 |
 +| SQL_ATTR_MAX_LENGTH | UINT | 바이트 길이 | 결과셋 안의 문자열 혹은 바이너리 컬럼의 최대 길이 |
 +| SQL_ATTR_MAX_ROWS | UINT | 행의 수 | 결과셋의 최대 행 수 |
 +| SQL_ATTR_METADATA_ID | UINT | SQL_TRUE \\ SQL_FALSE | 대소문자 구별 여부. 이외에도 뭔가 있다. |
 +| SQL_ATTR_NOSCAN | UINT | SQL_NOSCAN_OFF \\ SQL_NOSCAN_ON | 이스케이프 문자 검색 여부 |
 +| SQL_ATTR_PARAM_BIND_OFFSET_PTR | UINT* | 포인터 옵셋 변수에 대한 포인터 | 동적 파라미터 바인딩 시에 더하는 값이라는데 뭔지 모르겠다. |
 +| SQL_ATTR_PARAM_BIND_TYPE | UINT | SQL_PARAM_BIND_BY_COLUMN \\  or 구조체의 크기 | [[http://​msdn.microsoft.com/​library/​default.asp?​url=/​library/​en-us/​odbc/​htm/​odbcbinding_arrays_of_parameters.asp | 음, 나중에 읽어보자]] |
 +| SQL_ATTR_PARAM_OPERATION_PTR | USINT* | SQL_PARAM_PROCEED,​ SQL_PARAM_IGNORE ​ 값으로 이루어진 배열에 대한 포인터 | [[http://​msdn.microsoft.com/​library/​en-us/​odbc/​htm/​odbcusing_arrays_of_parameters.asp | 배열을 한번에 바인딩하는 것과 관련된 속성인 듯?]] |
 +| SQL_ATTR_PARAM_STATUS_PTR | USINT* | 배열의 포인터 | 쿼리 실행 결과를 받아오기 위한 배열 |
 +| SQL_ATTR_PARAMS_PROCESSED_PTR | UINT* | 배열의 포인터 | 리 실행 결과를 받아오기 위한 배열 |
 +| SQL_ATTR_PARAMSET_SIZE | UINT | 한 파라미터에 들어있는 값의 숫자 | 배열을 바인딩하기 위해 설정하는 값 |
 +| SQL_ATTR_QUERY_TIMEOUT | UINT | 초 | 쿼리를 수행하고 결과셋을 기다릴 시간, 0 == INFINITE |
 +| SQL_ATTR_RETRIEVE_DATA | UINT | SQL_RD_ON \\ SQL_RD_OFF | 커서가 움직이면 데이터를 바로 가져오는지 여부 |
 +| SQL_ATTR_ROW_ARRAY_SIZE | UINT | 행의 수 | 결과셋을 페치할 때마다 가져올 행의 수 |
 +| SQL_ATTR_ROW_BIND_OFFSET_PTR | UINT* | ? | ? |
 +| SQL_ATTR_ROW_BIND_TYPE | UINT | ? | ? |
 +| SQL_ATTR_ROW_NUMBER | UINT | 행 번호 | 현재 행이 전체 결과셋에서 차지하는 번호 |
 +| SQL_ATTR_ROW_OPERATION_PTR | USINT* | ? | ? |
 +| SQL_ATTR_ROW_STATUS_PTR | | USINT* | |
 +| SQL_ATTR_ROWS_FETCHED_PTR | UINT* | 행 갯수를 집어넣을 변수의 포인터 | 결과셋을 가져올 때마다 안의 행 숫자를 집어넣을 변수 설정 |
 +| SQL_ATTR_SIMULATE_CURSOR | UINT | SQL_SC_NON_UNIQUE \\ SQL_SC_TRY_UNIQUE | Positioned update and delete statements? |
 +| SQL_ATTR_USE_BOOKMARKS | UINT | SQL_UB_OFF \\ SQL_UB_VARIABLE | 북마크 사용 여부 |
 +
 +===== BLOB/TEXT 컬럼 사용시 유의점 =====
 +SQLGetData 함수를 이용해 BLOB/TEXT 컬럼을 읽어올 때에는, BLOB/TEXT 컬럼이 SELECT 구문의 마지막에 오도록 해야한다.
 +<code sql>
 +SELECT ID, BLOB_COLUMN,​ INT_COLUMN FROM SomeTable -- ERROR
 +SELECT ID, INT_COLUMN, BLOB_COLUMN FROM SomeTable -- OK
 +</​code>​
 +
 +자세한 사항은 [[http://​msdn.microsoft.com/​library/​default.asp?​url=/​library/​en-us/​odbc/​htm/​odbcgetting_long_data.asp | Getting Long Data]] 페이지를 참고.
 +
 +//There are a number of restrictions on using SQLGetData. In general, columns accessed with SQLGetData: //
 +  * //Must be accessed in order of increasing column number (because of the way the columns of a result set are read from the data source). For example, it is an error to call <​code>​SQLGetData</​code>​ for column 5 and then call it for column 4.//
 +  * //Cannot be bound.//
 +  * //Must have a higher column number than the last bound column. For example, if the last bound column is column 3, it is an error to call SQLGetData for column 2. For this reason, **applications should be careful to place long data columns at the end of the select list.**//
 +  * //Cannot be used if <​code>​SQLFetch</​code>​ or <​code>​SQLFetchScroll</​code>​ was called to retrieve more than one row.''//​
 +
 +
 +===== Connection String =====
 +SQLDriverConnect에 사용하는 주소 문자열.
 +<​code>​
 +connection-string ::= empty-string[;​] | attribute[;​] | attribute; connection-string
 +empty-string ::=
 +attribute ::= attribute-keyword=attribute-value | DRIVER=[{]attribute-value[}]
 +attribute-keyword ::= DSN | UID | PWD
 +         | driver-defined-attribute-keyword
 +attribute-value ::= character-string
 +driver-defined-attribute-keyword ::= identifier
 +</​code>​
 +
 +SQL Server
 +<​code>​
 +DRIVER=SQL Server;​SERVER=myserver;​DATABASE=testdb;​Trusted_Connection=Yes
 +DRIVER=SQL Server;​SERVER=myserver;​DATABASE=testdb;​UID=testuser;​PWD=testpwd
 +</​code>​
 +
 +File DSN
 +<​code>​
 +FILEDSN=C:​\sample.dsn
 +</​code>​
 +
 +sample.dsn
 +<​code>​
 +DRIVER = SQL Server
 +UID = Larry
 +DATABASE = MyDB
 +</​code>​
 +
 +:!: File DSN에는 패스워드를 지정할 수 없다.
 +
 +===== Scrollable Cursor =====
 +별다른 옵션을 주지 않을 경우, 기본적으로 생성되는 커서는 forward-only 커서다. 커서를 앞뒤로 움직이거나,​ 특정 옵셋으로 가기 위해서는 scrollable cursor 를 사용해야한다.
 +
 +<code cpp>
 +// Statement 핸들에다가 사용할 커서의 타입과 한번에 가져올 행의 갯수를 설정한다.
 +SQLSetStmtAttr(hStmt,​ SQL_ATTR_ROW_ARRAY_SIZE,​ (SQLPOINTER)1,​ 0);
 +SQLSetStmtAttr(hStmt,​ SQL_ATTR_CURSOR_SCROLLABLE,​ (SQLPOINTER)SQL_SCROLLABLE,​ 0);
 +...
 +// SQLFetchScroll 함수를 통해 결과셋을 가져온다.
 +SQLFetchScroll(hStmt,​ SQL_FETCH_NEXT,​ 0);
 +SQLFetchScroll(hStmt,​ SQL_FETCH_PRIOR,​ 0);
 +</​code>​
 +
 +===== Connection Pooling =====
 +커넥션 풀링이 뭐하는 기능인지는 이름이 다 말해주고 있다. 서버와의 커넥션을 만드는 비용이 비싸기 때문에 애플리케이션 레벨에서 커넥션을 닫아도 실제로 닫지는 않고 있다가 해당 서버와의 연결 요청이 들어오면 기존의 커넥션을 재이용하는 기능이다. 기본적으로 커넥션 스트링을 이용해 커넥션을 구분한다. 같은 서버에 연결한다고 하더라도 커넥션 스트링이 한 바이트라도 틀리면 다른 커넥션으로 인식한다는 이야기다.
 +
 +커넥션 풀링을 사용할 때 주의할 점은 다음과 같다.
 +
 +  * 데이터베이스 변경 (USE XXX)
 +  * 세팅 변경 (SET NOCOUNT ON)
 +  * 임시 객체 생성 (커넥션이 '​풀링'​되므로 커넥션 자체가 사라지기 전까지 계속 존재하게 된다)
 +
 +커넥션 풀링을 사용할 때 살펴볼 값 중의 하나가 CPTimeout 값과 RetryWait 값이다. CPTimeout 값은 사용하고 있지 않은 커넥션을 풀에 담아둘 시간이고,​ RetryWait 값은 서버에서 응답이 없을 경우, 다음 커넥션 재생성을 위해 기다릴 시간이다.
 +
 +RetryWait 값은 제어판 -> 관리도구 -> 데이터원본 (ODBC) -> 연결 풀링 탭에서 수정할 수 있다. CPTimeout 값은 해당 드라이버를 더블 클릭하면 뜨는 윈도우에서 수정할 수 있다. 레지스트리에서도 수정할 수 있다. <​nowiki>​HKLM\Software\Odbc\Odbcinst.ini\<​drivername></​nowiki>​ 항목을 찾아보기 바란다. 값은 초단위다.
 +
 +풀링은 ODBC API를 통해 설정할 수도 있다. ​
 +<code cpp>
 +SQLSetEnvAttr(
 +    hEnv, 
 +    SQL_ATTR_CONNECTION_POOLING, ​
 +    ULongToPtr(SQL_CP_ONE_PER_HENV or SQL_CP_ONE_PER_DRIVER), ​
 +    SQL_IS_UINTEGER
 +    );
 +</​code>​
 +
 +  * SQL_CP_ONE_PER_HENV - 같은 HENV를 공유하는 모든 커넥션 풀링
 +  * SQL_CP_ONE_PER_DRIVER - 드라이버별로 커넥션 풀링. 같은 드라이버만 사용한다면 HENV랑 별 차이가 없다.
 +
 +//내부 네트워크 부하에 의해, 커넥션이 이상하게 끊어지는 경우가 있다고 한다. 이 문제를 해결하기 위해서 쿼리를 실행할 때마다 커넥션 객체를 생성하되,​ 커넥션 풀링을 이용하라...라는 이야기가 있던데...//​
 +
 +//커넥션 풀링을 사용하는 애플리케이션을 빠르게 실행했다,​ 죽였다를 반복하면,​ SQLConnect 내부에서 Access Violation이 발생하는 경우가 있었다. 윈도우즈 2003 서버, SQL Server 2005 기준이다. 설정이 뭔가 잘못된 것인지, ODBC 내부 문제인지 모르겠네.//​
 +
 +//​찾아보니 [[http://​support.microsoft.com/?​kbid=904422 | 이런 글]]이 있었다. 이 문제가 맞나? .NET 이랑은 아무 관련 없는데... [[http://​support.microsoft.com/?​kbid=328476 요런 글]]도 있고...//
 +
 +
 +====== 링크 ======
 +  * [[http://​msdn.microsoft.com/​library/​default.asp?​url=/​library/​en-us/​odbc/​htm/​odbcabout_this_manual.asp | ODBC Programmer'​s Reference]]
 +  * [[http://​www.dbmaker.com/​reference/​manuals/​odbc/​odbc_toc.html | ODBC Programmer'​s Guide]] \\ 
 +    * 온라인북
 +    * [[http://​www.dbmaker.com/​download/​manual/​odbc.pdf | PDF 버전]]도 있다. ​
 +  * [[http://​www-106.ibm.com/​developerworks/​db2/​library/​techarticle/​dm-0409kartha/?​ca=dgr-lnxw16DerbyODBC | ODBC programming using Apache Derby]]
 +  * [[http://​msdn2.microsoft.com/​en-us/​library/​ms811006.aspx | Using ODBC with Microsoft SQL Server]]
 +  * [[http://​www.codeproject.com/​database/#​ODBC | CodeProject > MFC,C++ > ODBC]]
 +
 +  * [[http://​www.easysoft.com/​developer/​interfaces/​odbc/​index.html]]
 +  * [[http://​www.datadirect.com/​developer/​odbc/​basics/​index.ssp]]
 +
 +  * [[http://​msdn.microsoft.com/​en-us/​library/​ms716287.aspx | MSDN > ODBC 64-Bit Information]]
 +  * [[http://​support.microsoft.com/​kb/​298678 | MSDN > ODBC 64-Bit API Changes in MDAC 2.7]]
 +
 +----
 +  * see also [[SqlServer]]
  
kb/odbc.txt · 마지막으로 수정됨: 2014/11/08 16:11 (바깥 편집)