平民程序 - linghuye's blog

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

随笔 - 221, 文章 - 0, 评论 - 680, 引用 - 0
数据加载中……

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 阅读(2822) 评论(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
只有注册用户登录后才能发表评论。