나만의 작은 도서관

[TIL][C++] 250828 MMO 서버 개발 89일차: C++의 ODBC API와 SQLBindParameter() 본문

Today I Learn

[TIL][C++] 250828 MMO 서버 개발 89일차: C++의 ODBC API와 SQLBindParameter()

pledge24 2025. 8. 29. 21:48
주의사항: 해당 글은 일기와 같은 기록용으로, 다듬지 않은 날것 그대로인 글입니다. 

C++의 ODBC API와 SQLBindParameter()

C++에서 제공하는 ODBC API

  • C++에서는 “sql.h”, “sqlext.h”m “sqltypes.h”와 같은 헤더 파일이 존재하며 이 헤더 파일들을 include 하면 ODBC API를 사용할 수 있다.
  • 제공하는 ODBC(Open DB Connectivity)는 개방형 데이터베이스 접속 표준으로, 어떤 DB 제품군(ex. Oralcle, SQL Server, MySql)을 사용하든 상관없이 일관된 인터페이스로 접근할 수 있다.
  • 게다가 특정 IDE(ex. Visual Studio, CLion)에도 구애받지 않기 때문에 어떤 IDE를 사용하든 컴파일러가 C++ 표준을 지원하고 ODBC 드라이버 및 헤더 파일에 접근할 수 있는 컴파일러라면 ODBC API를 활용할 수 있다.

 

SQLBindParameter() 함수

  • SQLBindParameter함수는 ODBC에서 SQL 문에 매개변수를 바인딩할 때 사용하는 함수. 여기서 매개변수란 ‘?’를 의미한다.
    • Ex. INSERT INTO Employee VALUES(?, ?, ?)

SQLBindParameter 함수 구조

SQLRETURN SQLBindParameter(  
      SQLHSTMT        StatementHandle,  
      SQLUSMALLINT    ParameterNumber,  
      SQLSMALLINT     InputOutputType,  
      SQLSMALLINT     ValueType,  
      SQLSMALLINT     ParameterType,  
      SQLULEN         ColumnSize,  
      SQLSMALLINT     DecimalDigits,  
      SQLPOINTER      ParameterValuePtr,  
      SQLLEN          BufferLength,  
      SQLLEN *        StrLen_or_IndPtr);
 );

 

매개변수 리스트 타입 설명

  • SQLRETURN: 함수의 실행 결과를 나타내는 타입
    • Ex. SQL_SUCCESS, SQL_SUCCESS_WITH_INFO, SQL_ERROR 등이 있음
  • SQLHSTMT: SQL문을 처리하기 위한 핸들(Handle). SQL 처리 담당 직원이라 생각하면 된다.
  • SQLUSMALLINT: unsigned 정수 타입.
  • SQLULEN: unsigned 긴 정수 타입. 주로 문자열 또는 바이너리 데이터의 최대 길이를 지정할 때 사용한다.
  • SQLPOINTER: 제너릭 포인터 타입. 바인딩할 매개변수의 값이 저장된 메모리 주소가 들어간다. (C++의 변수 포인터가 들어간다는 뜻)
  • SQLLEN: 긴 정수 타입. SQL문에서 활용하는 데이터의 논리적인 길이를 의미한다.
    • 버퍼의 실제 길이, 데이터 길이 또는 NULL 여부 지정에 사용.

매개변수 상세 설명

SQLRETURN SQLBindParameter(  
      SQLHSTMT        StatementHandle,  -> SQL문 핸들
      SQLUSMALLINT    ParameterNumber,  -> 바인딩할 매개변수 번호(1부터 시작)
      SQLSMALLINT     InputOutputType,  -> 매개변수 입출력 타입 설정
      SQLSMALLINT     ValueType,        -> 매개변수의 C언어 데이터 타입
      SQLSMALLINT     ParameterType,    -> 매개변수의 SQL 데이터 타입
      SQLULEN         ColumnSize,       -> SQL 기준 타입 최대 길이. ex. VARCHAR(50)이면 50을 지정
      SQLSMALLINT     DecimalDigits,    -> 소수점 이하 자릿수 지정
      SQLPOINTER      ParameterValuePtr,-> 바인딩할 변수의 주소  
      SQLLEN          BufferLength,     -> ParameterValuePtr이 가리키는 버퍼의 길이(크기?)
      SQLLEN *        StrLen_or_IndPtr); -> 바인딩 변수의 실제 길이 또는 Null 여부 포인터
}

 

InputOutputType 종류

  • SQL_PARAM_INPUT: 데이터를 DB로 전달. 가장 많이 사용되며 프로시저 호출이 아닌 경우 100% 이거다.
  • SQL_PARAM_OUTPUT: DB에서 결과를 받는 타입.
    • ?=call GetNextEmpID
  • SQL_PARAM_INPUT_OUTPUT: 데이터를 DB로 전달하고, 그 결과를 다시 받는다.

 

고정 길이 타입과 가변 길이 타입 처리하는 법

  • 타입을 다룰 때 int, float, bool과 같은 고정 길이 타입이 있고, 문자열, 바이너리 데이터와 같은 가변 길이 타입이 있다. SQLBindParameter는 데이터 타입에 따라 바인딩할 때 사용하는 인자가 다르다.

고정 길이 타입

  • 고정 길이 타입의 데이터의 경우, 사용자가 추가적으로 데이터 길이를 알려주지 않아도 데이터 길이를 알 수 있다. 따라서, 가변 길이에서만 사용하는 인자들은 넣어주긴 하되 내부적으로 무시된다. 무시되는 인자는 다음과 같다.
    • BufferLength
    • StrLen_or_IndPtr
  • 추가적으로 ColumnSize의 경우 일부 타입은 무시된다.

가변 길이 타입

  • 가변 길이 타입의 데이터의 경우, 사용자가 추가적으로 데이터 길이를 알려줘야 한다. 즉, 바이너리 타입과 문자열 타입은 고정 길이 타입에서 무시한 BufferLength와 StrLen_or_IndPtr을 설정해줘야 한다.
    • BufferLength는 데이터를 담을 버퍼의 최대 크기를 지정한다.
    • StrLen_or_IndPtr: 버퍼에 들어있는 실제 데이터의 크기를 넣어준다. 아니면 SQL_NTS와 같은 특별한 값으로 데이터의 끝을 알리는 문자를 지정한다.
[-------데이터-------________]
BufferLength = 버퍼의 최대 길이
StrLen_or_IndPtr = 데이터의 길이(바이트 단위)

char name[100] = "John";  // 버퍼는 100바이트
SQLLEN actualLength = 4;  // 실제 데이터는 4바이트

SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, 
                 50, 0, name, 100, &actualLength);

 

어떻게 가변 길이로 판단되는가?

  • valueType과 parameterType으로 판단한다. valueType이 SQL_C_CHAR, SQL_C_WCHAR, SQL_C_BINARY와 같은 타입이고, parameterType이 SQL_VARCHAR, SQL_NVARCHAR, SQL_VARBINARY와 같은 타입이면 가변 길이로 판단한다.