使用ADO读出的BIGINT字段类型,形成的VARIANT是VT_DECIMAL类型

本文总结了使用M$SQL过程中遇到的问题,包括ADO读取BIGINT字段类型的问题、SQL查询分析器的使用误区以及存储过程调用的复杂性。提供了一种通过ODBC API直接调用存储过程的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

平民程序 - linghuye's blog

天下风云出我辈,一入江湖岁月催。皇图霸业谈笑中,不胜人生一场醉。提剑跨骑挥鬼雨,白骨如山鸟惊飞。尘事如潮人如水,只笑江湖几人回。

随笔 - 203, 文章 - 0, 评论 - 516, 引用 - 0

导航

公告

愿绵泊的悲哀浸透我颓废的一生

围在城里的人想逃出来,城外的人想冲进去,对婚姻也罢,职业也罢,人生的愿望大多如此.

常用链接

留言簿(106)

随笔分类

随笔档案

收藏夹

友情链接

目前常用链接

<script language="javascript"> function searchgoogle(key,evt,site) { if(evt.keycode==13 || evt.keycode==0 || evt.type =='click') { key.focus(); var keystr = encodeuricomponent(key.value); url = "http://www.google.com/search?q="; url = url+keystr; url += "&ie=utf-8&oe=gb2312&hl=zh-cn&domains="+site+"&sitesearch="+site; window.location=url; return false; } } </script>

搜索

  •  

最新评论

阅读排行榜

评论排行榜

M$ SQL的问题

最近用M$ SQL的遇到些问题,总结一下.

1. 使用ADO读出的BIGINT字段类型,形成的VARIANT是VT_DECIMAL类型,而非想象中的VT_I8.更要命的是 VariantChangeType在Win2000下转换VT_DECIMAL->VT_I8或反之,都出错,该API返回错误的数据类型,而 WinXP和Win2003下不会.结论是Win2000内核对VT_I8支持有误,当前SP4仍为解决该问题.Bae, Hyun-jik给出一个hack绕过该问题. Refer to:
http://groups.google.com/group/microsoft.public.data.oledb/browse_thread/thread/3ba6ff6e76186d95/c89a98d77a8fdb52?lnk=st&q=vt_decimal+to+vt_i8&rnum=1&hl=zh-CN#c89a98d77a8fdb52
http://groups.google.com/group/microsoft.public.win32.programmer.ole/browse_thread/thread/ee793c37192460d8/3f3ca1b412620ac6?lnk=st&q=vt_decimal+to+vt_i8&rnum=2&hl=zh-CN#3f3ca1b412620ac6

2.不能在SQL查询分析器下,选择文本的状态下,然后F5执行查询,执行的是选择文本.偶不知道,检查了4个小时的语法后发现的.

3.ADO的Command对象带参数存储过程调用方式真低能,一个一个Parameter对象地创建,设置,赋值,这样的方式写出的都是垃圾代码.
改 用adCmdText方式直接进行SQL语法调用EXECUTE procname @varInput,却无法从ADO的Command对象中取得返回值,于是被逼使用SELECT ErrCode = 1记录集返回.这样,对于复杂的存储过程中间多次进行出错返回的,出现多个SELECT语句,此时ADO将返回的一个多数据集对象,其中只有一个为打开, 其他均为关闭,(奇怪的逻辑),于是有如下丑陋的代码:
int ExecuteStoreProcedure(const char* szSQL)
{
 try
 { 
  _variant_t vRecords;
  _RecordsetPtr ptrRcs = m_ptrConnection->Execute(_bstr_t(szSQL), &vRecords, adOptionUnspecified);
  while(ptrRcs != NULL)
  { 
   if(ptrRcs->GetState() == adStateOpen)
   {
    return ptrRcs->GetFields()->GetItem("ErrCode")->GetValue();
   }
   ptrRcs = ptrRcs->NextRecordset(&vRecords);
  }
  return ERROR_UNKNOWN;
 }
 catch(_com_error& e)
 { 
  _bstr_t bstrErrMsg = e.Description();
  DUMP_COM_ERROR(e);
  return ERROR_UNKNOWN;
 }
 catch(...)
 {
  return ERROR_UNKNOWN;
 }
}

只是不知有没更简单的方法取回存储过程的return值,在使用直接SQL执行调用的方式下!
推荐大家使用MYSQL.

posted on 2006-06-29 17:29 linghuye 阅读(379) 评论(2)  编辑 收藏 引用 所属分类: 编程札记

评论

# re: M$ SQL的问题  回复  更多评论   

ADO的效率确实是不敢恭维。不过还在还有ODBC SQL API直接获取存储过程的方法。不用写ADO比较蹩脚的代码。(据说DB Lib是专门针对MSSQL优化的,实际测试一点都没有看出来,还是ODBC API速度比较稳定。)
以前写了一个,速度比AD快很多,主要是没有那些乱七八糟的属性,直来直去比较方便省事。博得楼主一笑。

void ODBCBase::ExecuteProc(char * szProcName,vector<string> vectorParam,int iPamaCount,int iReCordCount, int * iResult, int * iRowCount,vector<RecordSetCell> * recordset)
{
SQLVARCHAR SqlPama[MAXPAMACOUNT][MAXPAMASIZE] = {'/0'}; //´´½¨Ò»¸ö¶þάÊý×éÀ´½ÓÊÕÊý¾Ý
SQLCHAR SqlColValue[MAXPAMACOUNT][MAXPAMASIZE]; //¶¨Òå½á¹û¼¯µÄ°ï¶¨ÁÐ
SQLINTEGER CountInd = 0;
int i;
char szLog[MAXCHARBUFF];
RecordSetCell cell;

*iRowCount = 0;

for(i = 0; i < vectorParam.size(); i++)
{
CopyMemory(SqlPama[i], vectorParam[i].c_str(), vectorParam[i].length());
}
CopyMemory(SqlPama[i], &CountInd, sizeof(BYTE)*2);

Retcode = SQLAllocHandle(SQL_HANDLE_STMT, Hdbc,&Hstmt);
if(SQL_SUCCESS != Retcode && SQL_SUCCESS_WITH_INFO != Retcode)
{
printf("/nSQL Set STMT Error.");
return;
}

if(Hstmt != NULL)
{
//°ó¶¨²ÎÊý
for(i=1 ;i<= iPamaCount; i++)
{
if(i == iPamaCount)
{
Retcode = SQLBindParameter(Hstmt, i, SQL_PARAM_OUTPUT, SQL_C_CHAR, SQL_VARCHAR, 2, 0, SqlPama[i - 1], 2, 0);
if(Retcode != SQL_SUCCESS && Retcode != SQL_SUCCESS_WITH_INFO)
{
printf("/nProc PARAM Error.");
return;
}
}
else
{
Retcode = SQLBindParameter(Hstmt, i, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, MAXPAMASIZE, 0, SqlPama[i - 1], MAXPAMASIZE, 0);
if(Retcode != SQL_SUCCESS && Retcode != SQL_SUCCESS_WITH_INFO)
{
printf("/nProc PARAM Error.");
return;
}
}
}

Retcode = SQLExecDirect(Hstmt, (SQLCHAR *)szProcName, SQL_NTS);
if(SQL_SUCCESS != Retcode && SQL_SUCCESS_WITH_INFO != Retcode)
{
SQLCHAR ConnStrOut[MAXBUFLEN];
SQLCHAR szErrorMsg[MAXBUFLEN];
SQLSMALLINT cbConnStrOut = 0;
SQLINTEGER nErrorCode = 0;
SQLSMALLINT nLenErrorMsg = 0;

Retcode = SQLGetDiagRec(SQL_HANDLE_STMT,
Hstmt,
1,
ConnStrOut,
&nErrorCode,
szErrorMsg,
MAXBUFLEN,
&nLenErrorMsg);

printf("%s/n", szErrorMsg);
sysLog->LogText((char *)szErrorMsg);
return;
}
else
{
printf("·µ»ØÖµ: %s/n", SqlPama[iPamaCount - 1]);
sprintf(szLog, "·µ»ØÖµ: %s", SqlPama[iPamaCount - 1]);
sysLog->LogText((char *)szLog);

//°ó¶¨ÁÐÃû
for(i = 1; i <= iReCordCount; i++)
{
SQLBindCol(Hstmt, i, SQL_C_CHAR, &SqlColValue[i-1], MAXBUFLEN, &CountInd);
}

*iResult = atoi((char *)SqlPama[iPamaCount - 1]);

//µÃµ½½á¹û¼¯
while(1)
{
Retcode = SQLFetch(Hstmt);
if(Retcode == SQL_SUCCESS || Retcode == SQL_SUCCESS_WITH_INFO)
{
for(i = 1;i <= iReCordCount; i++)
{
SQLGetData(Hstmt, i, SQL_VARCHAR, &SqlColValue[i-1], MAXBUFLEN, &CountInd);
//printf(", %s",SqlColValue[i-1]);
//½«Êý¾Ý¸´ÖƵ½Ò»¸ö½á¹¹ÖÐ,È»ºó°ÑÕâ¸ö½á¹¹´«Èëvector
cell.iCol = i;
cell.iRow = *iRowCount;
cell.strCellText = string((char *)SqlColValue[i-1]);

recordset->push_back(cell);
}
//printf("/n");
*iRowCount = *iRowCount + 1;
}
else
{
SQLCHAR ConnStrOut[MAXBUFLEN] = {'/0'};
SQLCHAR szErrorMsg[MAXBUFLEN] = {'/0'};
SQLSMALLINT cbConnStrOut = 0;
SQLINTEGER nErrorCode = 0;
SQLSMALLINT nLenErrorMsg = 0;

Retcode = SQLGetDiagRec(SQL_HANDLE_STMT,
Hstmt,
1,
ConnStrOut,
&nErrorCode,
szErrorMsg,
MAXBUFLEN,
&nLenErrorMsg);

printf("%s/n", szErrorMsg);
break;
}
}
}
}
2006-06-30 11:25 | freeeyes

# re: M$ SQL的问题  回复  更多评论   


Retcode = SQLFreeHandle(SQL_HANDLE_STMT, Hstmt);
if(Retcode != SQL_SUCCESS && Retcode != SQL_SUCCESS_WITH_INFO)
{
printf("Free Hstmt Error");
}

}
2006-06-30 11:28 | freeeyes


标题
姓名
主页
验证码*
内容(提交失败后,可以通过“恢复上次提交”恢复刚刚提交的内容)

  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
[使用Ctrl+Enter键可以直接提交]
 
相关链接:


marginheight="0" marginwidth="0" src="http://www.cnitblog.com/ad.htm" style="border: 0px solid rgb(102, 102, 102);" allowtransparency="true" frameborder="0" height="60" scrolling="no" width="468">
51YES网站统计系统 marginwidth="0" marginheight="0" hspace="0" vspace="0" src="http://count4.51yes.com/sa.aspx?id=45505990&refe=&location=http%3A//www.cnitblog.com/linghuye/archive/2006/06/29/13070.html&color=32x&resolution=1600x900&returning=0&language=undefined&ua=Mozilla/5.0%20%28Windows%3B%20U%3B%20Windows%20NT%205.1%3B%20zh-CN%3B%20rv%3A1.8.1.17%29%20Gecko/20080829%20Firefox/2.0.0.17" frameborder="0" height="0" scrolling="no" width="0">
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值