SQLRU.net
Разработка приложений баз данных

Начало » Программирование » C++ » MS Sql: определить типы полей рекодсета из программы
MS Sql: определить типы полей рекодсета из программы [сообщение #4230] Wed, 24 January 2024 19:14 Переход к предыдущему сообщению
badhabit в настоящее время не в онлайне  badhabit
Сообщений: 7
Зарегистрирован: January 2024
Junior Member
Добрый день. Никак не получается корректно определить тип полей полученного рекодсета.
Например делаю таблицу:
use test

drop table if exists tbl
create table tbl
(
    fld_date date
    , fld_datetime datetime
    , fld_time time
    , fld_varchar varchar(50)
    , fld_int int
    , fld_float float
)
insert into tbl
select
'20220914'
, '20220914 15:12:33'
, '12:34:22'
, 'test string'
, 123
, 123.45
Потом пытаюсь определить тип каждого поля:
#include <iostream>
#include <string>
#include <msdasc.h>

#import "msado15.dll" no_namespace rename("EOF", "adoEOF")

std::string Type2Str(DataTypeEnum type)
{
    std::string sResult;
    switch (type)
    {
        case 0x2000: sResult = "AdArray"; break;
        case 20: sResult = "adBigInt"; break;
        case 128: sResult = "adBinary"; break;
        case 11: sResult = "adBoolean"; break;
        case 8: sResult = "adBSTR"; break;
        case 136: sResult = "adChapter"; break;
        case 129: sResult = "adChar"; break;
        case 6: sResult = "adCurrency"; break;
        case 7: sResult = "adDate"; break;
        case 133: sResult = "adDBDate"; break;
        case 134: sResult = "adDBTime"; break;
        case 135: sResult = "adDBTimeStamp"; break;
        case 14: sResult = "adDecimal"; break;
        case 5: sResult = "adDouble"; break;
        case 0: sResult = "adEmpty"; break;
        case 10: sResult = "adError"; break;
        case 64: sResult = "adFileTime"; break;
        case 72: sResult = "adGUID"; break;
        case 9: sResult = "adIDispatch"; break;
        case 3: sResult = "adInteger"; break;
        case 13: sResult = "adIUnknown"; break;
        case 205: sResult = "adLongVarBinary"; break;
        case 201: sResult = "adLongVarChar"; break;
        case 203: sResult = "adLongVarWChar"; break;
        case 131: sResult = "adNumeric"; break;
        case 138: sResult = "adPropVariant"; break;
        case 4: sResult = "adSingle"; break;
        case 2: sResult = "adSmallInt"; break;
        case 16: sResult = "adTinyInt"; break;
        case 21: sResult = "adUnsignedBigInt"; break;
        case 19: sResult = "adUnsignedInt"; break;
        case 18: sResult = "adUnsignedSmallInt"; break;
        case 17: sResult = "adUnsignedTinyInt"; break;
        case 132: sResult = "adUserDefined"; break;
        case 204: sResult = "adVarBinary"; break;
        case 200: sResult = "adVarChar"; break;
        case 12: sResult = "adVariant"; break;
        case 139: sResult = "adVarNumeric"; break;
        case 202: sResult = "adVarWChar"; break;
        case 130: sResult = "adWChar"; break;
        default: sResult = "err"; break;
    }
    return sResult;
}

void main()
{
    CoInitialize(NULL);

    _ConnectionPtr pConnection = NULL;
    _RecordsetPtr rs = NULL;
    try
    {
        pConnection.CreateInstance(__uuidof(Connection));
        pConnection->CommandTimeout = 0;
        std::string sConnectionString = "Provider=SQLOLEDB.1;Trusted_Connection=True;Initial Catalog=test;User ID=sa;Password=sa;Data Source=localhost";
        pConnection->Open(_bstr_t(sConnectionString.c_str()), _bstr_t(""), _bstr_t(""), adModeUnknown);
                
        HRESULT hr = rs.CreateInstance(__uuidof(Recordset));
        rs->CursorType = adOpenForwardOnly;
        rs->CursorLocation = adUseServer;
        rs->LockType = adLockReadOnly;
        rs->Open((_bstr_t)"select * from tbl", (IDispatch*)pConnection, adOpenForwardOnly, adLockReadOnly, adCmdText);

        _variant_t vtFldIdx;
        vtFldIdx.vt = VT_I2;
        for (vtFldIdx.iVal = 0; vtFldIdx.iVal < rs->Fields->GetCount(); vtFldIdx.iVal++)
        {
            std::cout << rs->Fields->GetItem(vtFldIdx)->Type << ": " << Type2Str(rs->Fields->GetItem(vtFldIdx)->Type) << std::endl;
        }


        rs->Close();
        pConnection->Close();
    }
    catch (_com_error& e)
    {
        std::cout << "COM err: " << (char*)e.Description() << std::endl;
        if (pConnection && (pConnection->State & adStateOpen) == adStateOpen) pConnection->Close();
        rs = NULL;
    }
    catch (...)
    {
        std::cout << "err" << std::endl;
        if (pConnection && (pConnection->State & adStateOpen) == adStateOpen) pConnection->Close();
        rs = NULL;
    }
}
Результат следующий:
202: adVarWChar
135: adDBTimeStamp
202: adVarWChar
200: adVarChar
3: adInteger
5: adDouble
т.е. тип date и time почему-то "не определились"...

поменял провайдер в строке подключения на:SQLNCLI11. Тип дат стал определятся нормально:
133: adDBDate
135: adDBTimeStamp
145: err
200: adVarChar
3: adInteger
5: adDouble
но теперь проблема с типом time(7), почему-то он определяется, как 145 что вообще не поименовано в enum DataTypeEnum, ну и при попытке преобразовать данные из колонки с типом time в строку:
std::string s = (const char*)_bstr_t(val);
вылетает исключение. Не подскажете, что можно сделать?
 
Сообщение не прочитано
Сообщение не прочитано
Сообщение не прочитано
Сообщение не прочитано
Сообщение не прочитано
Сообщение не прочитано
Сообщение не прочитано
Сообщение не прочитано
Сообщение не прочитано
Сообщение не прочитано
Сообщение не прочитано
Сообщение не прочитано
Сообщение не прочитано
Сообщение не прочитано
Сообщение не прочитано
Предыдущая тема: Проект CMake (MSVS 2022), задать precompiled header
Следующая тема: собрать fbclient.lib под bcc64 (embarcadero clang)
Переход к форуму:
  


Текущее время: Thu May 09 07:24:32 GMT+3 2024

Общее время, затраченное на создание страницы: 0.00772 секунд