VC調用預存程序的通用方法(SQLServer篇)

來源:互聯網
上載者:User

這裡討論的是ADO調用預存程序,按MSDN的例子,一般都是下面的調用方法(節選自MSDN):

HRESULT hr = S_OK;

    // Define ADO object pointers.
    // Initialize pointers on define.
    // These are in the ADODB::  namespace.
    _RecordsetPtr pRstByRoyalty = NULL;
    _RecordsetPtr pRstAuthors = NULL; 
    _CommandPtr   pcmdByRoyalty = NULL;
    _ParameterPtr pprmByRoyalty = NULL;
    _ConnectionPtr pConnection = NULL;

    _bstr_t strCnn("Provider=sqloledb;Data Source=srv;"
        "Initial Catalog=Pubs;User Id=sa;Password=;");

    _bstr_t strMessage, strAuthorID;
    int intRoyalty;
    VARIANT vtRoyalty;

    try
    {
        //Open a Connection.
        TESTHR(pConnection.CreateInstance(__uuidof(Connection)));
        hr = pConnection->Open(strCnn,"","",NULL);
        pConnection->CursorLocation = adUseClient;

        //Open Command Object with one Parameter
        TESTHR(pcmdByRoyalty.CreateInstance(__uuidof(Command)));
        pcmdByRoyalty->CommandText = "byroyalty";
        pcmdByRoyalty->CommandType = adCmdStoredProc;

        //Define Integer/variant.
        vtRoyalty.vt = VT_I2;
        vtRoyalty.iVal = intRoyalty;
        pprmByRoyalty = pcmdByRoyalty->CreateParameter(
            "percentage",adInteger,adParamInput,sizeof(int),vtRoyalty);
        pcmdByRoyalty->Parameters->Append(pprmByRoyalty);
        pprmByRoyalty->Value  = vtRoyalty;

        //Create Recordset by executing the command
        pcmdByRoyalty->ActiveConnection = pConnection;
        pRstByRoyalty = pcmdByRoyalty->Execute(
            NULL,NULL,adCmdStoredProc);

       //執行結果的處理,省略...

        pRstByRoyalty->Close();
        pRstAuthors->Close();
        pConnection->Close();
    }

    catch(_com_error &e)
    {
       //意外處理...
    }
}

必須指定執行SQL語句的CommandType是adCmdStoredProc,預存程序有參數就必須CreateParameter產生參數,這樣調用預存程序就成了很麻煩的一件事情,必須針對不同的預存程序產生不同的參數。一個兩個還可以接受,如果項目的商務邏輯比較複雜,需要依賴大量的預存程序,並且項目的需求或功能可能要經常變動或擴充,那就成了一個噩夢了。有沒有通用的方法呢?當然有,只需要通用的查詢就可以實現。

_ConnectionPtr pConnection = NULL;
m_Conn.CreateInstance(__uuidof(Connection));
m_Conn->ConnectionString = "Provider=sqloledb;Data Source=srv;"Initial Catalog=Pubs;User Id=sa;Password=;";
m_Conn->Open("","","",NULL);

_variant_t m_param;
 _bstr_t m_bstr;
int index = 0,nFieldCount;
_RecordsetPtr m_Rs;
m_Rs.CreateInstance(__uuidof(Recordset));
m_Rs->Open("select * from titles",(IDispatch*)(m_Conn->m_Conn),adOpenStatic,    adLockReadOnly,adCmdText);
nFieldCount = m_Rs->Fields->Count;
while(!m_Rs->EndOfFile)
{
   for(index=0;index < nFieldCount;index ++)
   {
      m_param.Clear();
      m_param = (short)index;
      m_param = m_Rs->Fields->GetItem(m_param);
      if(m_param.vt != VT_NULL)
          m_bstr = m_param;
      else
          m_bstr = "";   
      printf("%s/n",(char*)m_bstr);
   }
   m_Rs->MoveNext();
}
m_Rs->Close();
m_Conn->Close();

以上一段就是普通的執行查詢SQL語句的代碼,簡單起見,去掉了所有防護和判斷代碼,對於MS SQLServer,如果是執行返回結果集的預存程序,比如Pubs的byroyalty,只需要把上面代碼中的"select * from titles"替換成"byroyalty 100"就可以了,即"過程名 參數1,參數2,..."形式。

這樣一來,不需要產生參數,只需要改變SQL語句,就實現了MS SQLServer預存程序的調用,可以通用。但是對於返回參數的預存程序,這段代碼就不行了,不過還是可以通過SQL語句解決:
“declare @q int exec checkpwd 'user','pwd',@ret = @q OUTPUT select @q”
checkpwd是一個預存程序,兩個輸入參數,使用者名稱和密碼,第三個是輸出參數@ret,返回使用者驗證的結果。通過執行上面的SQL語句,把輸出參數作為結果集返回,就可以適應上面的VC代碼了。傳回值的預存程序也是一樣,執行“declare @q int,@return int exec @return = checkpwd 'user','pwd',@ret = @q OUTPUT select @q,@return”就可以了。

這裡講的是SQLServer的預存程序調用,這段代碼同樣可以調用ORACLE的預存程序,不過需要對SQL語句作出一些調整,留待下一篇再說了。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.