2

Я пишу небольшое консольное приложение на C++ (VS 2013/Windows7), в котором используется собственный клиент SQL Server sqlncli.h. У меня проблемы с полями NULL в программе - я не вижу правильных значений. СтруктураВозвращает типы данных NULL в C++ native client из SQL Server

#include <windows.h> 

#include <sql.h> 
#include <sqlext.h> 
#include <sqltypes.h> 
#include <sqlncli.h> 

#include <cstdio> 
#include <string> 
#include <iostream> 

using namespace std; 

int main() 
{ 
    SQLHENV environHandle; 
    SQLHDBC connectHandle; 
    SQLHSTMT statement; 
    SQLWCHAR* connectString = (SQLWCHAR*)TEXT("Driver={SQL Server};Server=XX.XX.XX.XX;Database=DBNAME;Trusted_Connection=yes;"); 
    SQLRETURN status; 
    status = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &environHandle); 
    cout << "SQLAllocHandle returned " << status << "\r\n"; 
    if (status == SQL_SUCCESS_WITH_INFO || status == SQL_SUCCESS) 
    { 
     status = SQLSetEnvAttr(environHandle, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3_80, SQL_IS_INTEGER); 
     cout << "SQLSetEnvAttr returned " << status << "\r\n"; 
     if (status == SQL_SUCCESS_WITH_INFO || status == SQL_SUCCESS) 
     { 
      status = SQLAllocHandle(SQL_HANDLE_DBC, environHandle, &connectHandle); 
      cout << "SQLAllocHandle SQL_HANDLE_DBC returned " << status << "\r\n"; 
      if (status == SQL_SUCCESS_WITH_INFO || status == SQL_SUCCESS) 
      { 
       status = SQLDriverConnect(connectHandle, NULL, connectString, SQL_NTS, NULL, 256, NULL, SQL_DRIVER_NOPROMPT); 
       cout << "SQLDriverConnect returned " << status << "\r\n"; 
       if (status == SQL_SUCCESS_WITH_INFO || status == SQL_SUCCESS) 
       { 
        status = SQLAllocHandle(SQL_HANDLE_STMT, connectHandle, &statement); 
        cout << "SQLAllocHandle SQL_HANDLE_STMT returned " << status << "\r\n"; 
        if (status == SQL_SUCCESS_WITH_INFO || status == SQL_SUCCESS) 
        { 
         status = SQLExecDirect(statement, (SQLWCHAR*)TEXT("SELECT * FROM [DBNAME].[dbo].[Table1]"), SQL_NTS); 
         cout << "SQLExecDirect returned " << status << "\r\n"; 
         if (status == SQL_SUCCESS_WITH_INFO || status == SQL_SUCCESS) 
         { 
          int rec_id; 
          int id; 
          char date[64]; 
          char ps[201]; 
          while (SQLFetch(statement) == SQL_SUCCESS) 
          { 
           SQLGetData(statement, 1, SQL_C_ULONG, &rec_id, 0, NULL); 
           SQLGetData(statement, 2, SQL_C_ULONG, &id, 0, NULL); 
           SQLGetData(statement, 3, SQL_C_CHAR, date, 64, NULL); 
           SQLGetData(statement, 4, SQL_C_CHAR, ps, 201, NULL); 
           cout << rec_id << " " << id << " " << date << " " << ps << endl; 
          } 
         } 
        } 
        cout << "Connected;"; 
        cin.get(); 
       } 
      } 
     } 
    } 
    return 0; 
} 

Table1:

CREATE TABLE [dbo].[Table1](
    [rec_id] [int] IDENTITY(1,1) NOT NULL, 
    [id] [int] NOT NULL, 
    [date] [datetime] NOT NULL, 
    [ps] [varchar](200) NULL 
) ON [PRIMARY] 

В консоли из я вижу первые 3 поля правильно, но четвертое поле, как ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠ Как catch NULL полей типа VARCHAR, NVARCHAR, FLOAT?

ответ

1

Последний аргумент для функции SQLGetData является

StrLen_or_IndPtr

[Выход] Указатель на буфер, в котором, чтобы вернуть длину или значение индикатора. Если это нулевой указатель, возвращается значение длины или . Это возвращает ошибку, когда данные, полученные , являются NULL. SQLGetData может возвращать следующие значения в буфере длины/индикатора:

Длина имеющихся данных для возврата
SQL_NO_TOTAL
SQL_NULL_DATA

Вы в настоящее время проходит NULL для этого, но если вы предоставите указатель на действительную переменную SQLLEN, то вы можете проверить возврат SQL_NULL_DATA.

Кроме того, если вы инициализируете свой буфер (например, char ps[201] = {0};), вы не получите распечатку мусора, если данные не будут возвращены для поля.

Смежные вопросы