ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • ODBC BindParametert 사용 시 문자열의 길이로는 SQL_NTS를 넣어줘야 한다.
    프로그래밍/의문 2015. 10. 28. 20:27
    반응형


    내가 실행할 쿼리


    const char* query = "{ call get_account_info_by_id ( ? ) }";


    인자로는 유저의 id를 받는다. 그리고 유저의 계정 정보를 반환한다.


    그런데 쿼리는 정상적으로 실행이 되는데, fetch의 반환 값이 SQL_NO_DATA인 것이었다.


    왜지? 존재하는 유저로 요청을 했는데?


    여기저기 검색을 해서 찾아봤는데, SQLBindParameter에 문자열을 쓰려면(출력 또는 입력으로)


    SQL_NTS를 인자를 줘야한다는 내용이 보였다. 


    그리고 정말 되나 실행해봤는데 검색이 정상적으로 되더라.


    1
    2
    3
    4
    5
    6
    7
    8
    9
        connector.prepare(query);
     
        // 쿼리의 출력 인자를 설정합니다.
        SQLINTEGER procreslen = SQL_NTS; // !!
     
        auto idlen = std::strlen(id.data());
     
        // 쿼리의 입력를 설정합니다.(id)
        connector.bind_parameter_in(SQL_C_CHAR, SQL_CHAR, id.size(), 0, (void*)id.data(), idlen, &procreslen); // id 설정
    cs


    (bind_parameter_in은 SQLBindParameter에 파라미터 타입 값을 SQL_PARAM_INPUT로 설정해둔 함수이다.)


    해당 부분의 전체적 소스코드.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    boost::optional<user_info> database_cache_server::get_user_info_from_database(const std::array<char, PACKET::max_id_length>& id)
    {
      constexpr char query[] = "{ call get_account_info_by_id ( ? ) }";
     
      std::lock_guard<decltype(load_data_mutex)> guard{ load_data_mutex };
     
      boost::optional<user_info> opt;
     
      // 쿼리를 준비합니다.
      if (connector.prepare(query))
      {
        // 쿼리의 출력 인자를 설정합니다.
        SQLINTEGER procreslen = SQL_NTS;
     
        auto idlen = std::strlen(id.data());
     
        // 쿼리의 입력를 설정합니다.(id)
        connector.bind_parameter_in(SQL_C_CHAR, SQL_CHAR, id.size(), 0, (void*)id.data(), idlen, &procreslen); // id 설정
     
        // select 값을 받을 변수들
        std::array<char20> out_id;
        std::array<wchar_t20> out_pw;
        std::array<wchar_t20> out_nickname;
        SQLINTEGER out_win = -1// win
        SQLINTEGER out_lose = -1// lose
     
        SQLINTEGER out_idlen = -1;
        SQLINTEGER out_pwlen = -1;
        SQLINTEGER out_nicknamelen = -1;
        SQLINTEGER out_winlen = sizeof(out_win);
        SQLINTEGER out_loselen = sizeof(out_lose);
     
        // select 결과 값을 받을 변수들을 지정합니다.(id, pw, nickname, win, lose)
        connector.bind_column(SQL_C_CHAR, out_id.data(), sizeof(out_id), &out_idlen); // id
        connector.bind_column(SQL_C_WCHAR, out_pw.data(), sizeof(out_pw), &out_pwlen); // pw
        connector.bind_column(SQL_C_WCHAR, out_nickname.data(), sizeof(out_nickname), &out_nicknamelen); // nickname
        connector.bind_column(SQL_C_SLONG, &out_win, sizeof(out_win), &out_winlen); // win
        connector.bind_column(SQL_C_SLONG, &out_lose, sizeof(out_lose), &out_loselen); // lose
     
        // 쿼리 실행
        if(connector.excute())
        {
          // 출력 결과를 받습니다.
          if (connector.fetch())
          {
            user_info info;
            info.id = out_id;
            info.pw = out_pw;
            info.nickname = out_nickname;
            info.num_win = out_win;
            info.num_lose = out_lose;
     
            opt = info;
          }
        }
      }
     
      // 커서를 닫습니다.
      connector.close_cursor();
     
      return opt;
    }
    cs


    어느정도 정리가 되면 커넥터 부분도 좀 더 깔끔하게 바꿔야겠다. stmt가 커넥터랑 하나로 뭉쳐있는 것도 그렇고 흐으으

    반응형
Designed by Tistory.