Начало » Программирование » C++ » MS Sql: определить типы полей рекодсета из программы
MS Sql: определить типы полей рекодсета из программы [сообщение #4230] |
Wed, 24 January 2024 19:14 |
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);
вылетает исключение. Не подскажете, что можно сделать?
|
|
|
|
|
|
|
|
|
|
|
Re: MS Sql: определить типы полей рекодсета из программы [сообщение #4301 является ответом на сообщение #4264] |
Wed, 31 January 2024 13:07 |
badhabit
Сообщений: 7 Зарегистрирован: January 2024
|
Junior Member |
|
|
SD писал(а) Sat, 27 January 2024 01:50 https://learn.microsoft.com/en-us/sql/relational-databases/n ative-client-ole-db-data-types/ssvariant-structure
Что-то я видимо ничего не понимаю... и в инете примеров совсем не нашел, ссылка только на эту статью хелпа... Не понимаю я, что надо в memcpy писать... Есть у меня значение ячейки в переменной _variant_t val; помогите её в DBTIME2 переделать...
#include <iostream>
#include <string>
#include <iostream>
#include <string>
#include <c:\Program Files\Microsoft SQL Server\110\SDK\Include\sqlncli.h>
#import "msado15.dll" no_namespace rename("EOF", "adoEOF")
void main()
{
CoInitialize(NULL);
SetConsoleOutputCP(1251);
SetConsoleCP(1251);
_ConnectionPtr pConnection = NULL;
_RecordsetPtr rs = NULL;
try
{
pConnection.CreateInstance(__uuidof(Connection));
pConnection->CommandTimeout = 0;
std::string sConnectionString = "Provider=SQLNCLI11;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;
_variant_t val = rs->Collect[vtFldIdx];
if (val.vt != VT_NULL)
{
if (rs->Fields->GetItem(vtFldIdx)->Type == DBTYPE_DBTIME2)
{
SSVARIANT ssDst = {0};
SSVARIANT* pssDst = &ssDst;
memcpy(&V_SS_TIME2(pssDst).tTime2Val, val, sizeof(DBTIME2)/*cbNative*/);
}
else
{
std::cout << (const char*)_bstr_t(val) << 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;
}
}
|
|
|
|
|
|
|
|
Переход к форуму:
Текущее время: Sun Nov 24 00:11:35 GMT+3 2024
Общее время, затраченное на создание страницы: 0.01087 секунд
|