나만의 작은 도서관

[TIL][C++] 250929 MMO 서버 개발 106일차: [C++ ODBC] SQLBindParameter()의 마지막 인자 StrLen_or_IndPtr에 대해서 헷갈려 했던 내용들 본문

Today I Learn

[TIL][C++] 250929 MMO 서버 개발 106일차: [C++ ODBC] SQLBindParameter()의 마지막 인자 StrLen_or_IndPtr에 대해서 헷갈려 했던 내용들

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

[C++ ODBC] SQLExecDirectW() 함수의 결과 코드가 100(SQL_NO_DATA)이 반환된 경우의 원인

  • SQL문을 실행하는 함수를 호출했을때 그 결과물로 SQLRETURN 타입이 반환된다. 이때 결과 코드가 100이 나왔다면 이는 SQL_NO_DATA 코드로, 행에 영향을 주는 쿼리(UPDATE, DELETE, INSERT)를 실행하였으나, 조건에 맞는 행이 없어 영향을 주지 못한 경우를 의미한다.
    • 즉, 조건을 만족하는 행이 테이블에 존재하지 않아서 SQL문을 실행하기 전과 후가 똑같다는 것
    • 대표적으로 UPDATE문의 WHERE에 맞는 행이 존재하지 않아 SET을 하지 못한 경우가 있다.

 

[C++ ODBC] SQLBindParameter() 에서 파라미터 배열과 단일 데이터를 바인딩할 때 들어가는 인자의 차이는 마지막 인자인 StrLen_or_indPtr 뿐이다.

  • SQLBindParameter에는 들어가는 인자가 굉장히 많은데, 파라미터 배열을 사용할 경우 달라지는 인자는 마지막 인자인 StrLen_or_IndPtr 뿐이다.
  • StrLen_or_IndPtr 인자는 단일 데이터인 경우 가변 길이 타입 데이터인 경우(Ex. 문자열) 값을 넣어주며, 이름에서 StrLen에 해당한다. 고정 길이 타입 데이터(Ex. 정수, 실수)인 경우 무슨 값을 넣어도 무시된다.
  • 반면, 파라미터 배열인 경우 고정 길이 타입이라도 값을 넣어줘야하는데, 이때 파라미터 배열 크기와 같은 크기의 배열의 포인터를 넣어줘야 한다. 이는 이름에서 IndPtr에 해당한다.
  • 지금까지의 내용을 정리하면 아래와 같다.

 

각 상황에 StrLen_or_IndPtr에 넣어줘야 하는 값

  • 단일 데이터(가변): 문자열의 길이가 담긴 변수. 길이를 직접 넣는 대신 끝 문자(Ex. NULL)를 넣어 문자열의 길이를 알 수 있도록 할 수도 있다.
  • 단일 데이터(고정): 0이 담긴 변수. 기본적으로 무슨 값을 넣어도 무시되긴 한다.
  • 파라미터 배열(고정): 파라미터 배열 크기와 같은 크기의 SQLLEN 배열. 각 원소에는 0또는 -1이 들어가 있다.

 

고정 길이 타입에서 StrLen_or_IndPtr에 배열을 넣어주는 이유는 무엇일까?

  • ODBC의 SQLBindParameter 함수에서 StrLen_or_IndPtr인자는 “모든 파라미터 형식에 대해 반드시 유효한 포인터를 지정해야한다.” 정수형과 같이 고정 길이 타입이라도 예외는 아니다.
  • 따라서 고정 길이 데이터(정수, 실수)의 경우에도, NULL 지원을 위해 StrLen_or_IndPtr 인자를 사용한다.
  • 내부적으로 IndPtr의 값이 0이면 Null이 아닌 유효한 값으로 판단하고, -1(SQL_NULL_DATA)인 경우 Null값으로 판단한다.

 

고정 길이 타입 경우 예시 코드(정수 파라미터 배열)

int32 values[MAXLEN] = {1, 2, 3};
SQLLEN indicators[MAXLEN];
for (int i = 0; i < MAXLEN; i++)
{
	if(i < 3/*실제 데이터 개수*/)
		indicators[i] = 0; // not null
	else
		indicators[i] = SQL_NULL_DATA; // null
}

SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0,
values, 0, indicators);

 

[C++ ODBC] SQLGetDiagRecW는 SQL_NO_DATA(100), SQLExecDirect는 SQL_NEED_DATA(99)가 반환되는 경우

  • 오류가 발생한 상태가 아니라, 실행할 SQL 문장에 Data-at-Execution 파라미터가 있어서 드라이버가 다음 단계(데이터 전송)를 요청하고 있는 “정상적인” 절차상의 중간 상태.
  • 파라미터 배열을 사용하는 상황에서 99가 반환되었다면, 높은 확률로 StrLen_or_IndPtr에 인자가 제대로 들어가지 않았을 확률이 높다. 개인적인 상황에서 배열이 아닌 0이 들어있는 단일 변수를 넣었을 때 이러한 문제가 발생했다.