很多朋友告诉我他数据库学得很好,对数据库的各类操作都相当熟练,没有难不到他们的SQL语句。然而他们写出的语句效率却并不是让人满意,一个读写就已经如此,要是成千上万频繁的数据库更新的话那个队列可能都要排到火星上去了。再者提到存储过程也是没人去做详细的了解,就更不提应用了。

  存储过程(Stored Procedure)是一组为了完成特定功能的SQL语句集,经编译后存储在数据库中。用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。存储过程是数据库中的一个重要对象,任何一个设计良好的数据库应用程序都应该用到存储过程。

  平常对于一条SQL语句需要先编译然后再执行,然后才能返回用户所需要的结果,但如果对于相同的SQL语句进行频繁多次的使用的话,每一次都重新编译然后执行,效率显然是大打折扣的。而正如百科里存储过程的介绍所说,能够将编译好的SQL语句存储在数据库中,之后每次调用便略过了编译这个步骤,只需要向存储过程传递参数(输入或输出)就能够得到用户需要的数据结果。当然,这对小量的数据库读写感觉不出来,但如果是大量的数据库操作,存储过程的优势就能够相当明显的体现出来。

  接下来我主要讲的是利用Visual C++对存储过程的调用。

  首先我们得引入msado15.dll动态链接库,他包含了ADO编程的一系列函数。

  #import “c:\program files\common files\system\ado\msado15.dll” no_namespace rename(“EOF”,”adoEOF”)  //将EOF改为adoEOF是为了避免与文件的结束符号混淆

  接下来就需要初始化Com库了,这里有两种方法,一种是

  ::CoInitialize(NULL);

  另一种是

  AfxOleInit();

  这两种区别在于AfxOleInit附带一些其它资源的支持,如果不需要OLE的一些功能的话用CoInitialize就可以了。另外一点区别在于用CoInitialize最后需要释放(CoUninitialize),而AfxOleInit则会自动完成。

  初始化完成COM库之后就可以开始建立数据库的连接了。

  _ConnectionPtr m_pConn;//数据库的Com智能指针

  m_pConn.CreateInstance(“ADODB.Connection”);

  //打开本地(localhost)上的TestDb数据库。利用sa身份与口令123456登陆。

  m_pConn->Open(“Driver={SQL Server};Server=localhost;Database=TestDB;UID=sa;PWD=123456″,”",”",adModeUnknown);

  有人会疑惑了,为什么m_pConn可以用对象的“.”又可以用指针的“->”?其实在C++里有一个叫“智能指针”的另类,既拥有对象的属性,又拥有指针的功能。像_ConnectionPtr,_RecordsetPtr等等都归属于这一范畴。

  到这里,我先用企业管理器创建一个存储过程,存储过程的名称为ProcTest。

  CREATE PROCEDURE ProcTest 
    @tusername    char(16),
    @tpassword    char(16),
    @retval        int        output
  AS 
     if exists(select * from Account where username=@tusername)
      BEGIN 
       if (select password from Account where username=@tusername)=@tpassword
        set @retval=0
      else
        set @retval=1
      END
    else
      set @retval=2
  GO

  这个存储过程的功能是通过传入用户名(tusername)与密码(tpassword),返回验证结果(retval)。如果帐号与密码都匹配便赋retval的值为0,密码错误赋retval的值为1,用户不存在赋retval的值为2。

  然后就开始创建执行存储过程的命令对象了。

  _CommandPtr m_pCmd;

  m_pCmd.CreateInstance(“ADODB.Command”);

  m_pCmd->ActiveConnection = m_pConn;

  m_pCmd->CommandText = “ProcTest”;  //存储过程为ProcTest

  接下来创建三个参数,分别是Input用户名,Input密码,Output验证结果。

  _ParameterPtr m_pParam_username;

  m_pParam_username.CreateInstance(“ADODB.Parameter”);

  m_pParam_username = m_pCmd->CreateParameter(“tusername”,adChar,adParamInput,16,”rock”);

  _ParameterPtr m_pParam_password;

  m_pParam_password.CreateInstance(“ADODB.Parameter”);

  m_pParam_password = m_pCmd->CreateParameter(“tpassword”,adChar,adParamInput,16,”123456″);

  _ParameterPtr m_pParam_result;

  m_pParam_result.CreateInstance(“ADODB.Parameter”);

  m_pParam_result = m_pCmd->CreateParameter(“retval”,adChar,adParamOutput,30,”");

  可以注意到两个是输入(adParamInput),一个是输出(adParamOutput),另外,如果是输入项第一个参数可以直接赋空,只需要在接下来的追加按存储过程里变量创建的顺序就可以了,但是做为良好的代码习惯,而且便于检查与阅读,最好还是赋上变量名。

  接下来追加m_pCmd里面去吧。

  m_pCmd->Parameters->Append(m_pParam_username);

  m_pCmd->Parameters->Append(m_pParam_password);

  m_pCmd->Parameters->Append(m_pParam_result);

  最后就可以执行了。

  m_pCmd->Execute(NULL,NULL,adCmdStoredProc);

  之后通过

  m_pCmd->Parameters->GetItem(_variant_t(“retval”))->GetValue();

  就可以获得返回值了。简单吧?

  这两天抽空写了两个类封装了下数据库的基本操作与存储过程,使用的时候只要在适当的地方加入头文件(DbOpt.h)然后建立对象就可以了,方法很简单。

点击下载