
支援 Access / Oracle / SQL Server 三大資料庫,介面模仿 Oracle SQL Plus,可執行任意 SQL 並顯示結果集或影響列數。
_ConnectionPtr m_pConnTemp;
HRESULT hr;
UpdateData();
// Oracle
CString strConn = _T("Provider=MSDAORA;Data Source=") + m_dbserver
+ _T(";User ID=") + m_username + _T(";Password=") + m_passwd;
// SQL Server
CString strConn = _T("Provider=SQLOLEDB.1;Data Source=") + m_dbserver
+ _T(";Initial Catalog=") + m_initDb
+ _T(";User ID=") + m_username + _T(";PWD=") + m_passwd;
// Access
CString strConn = _T("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=") + m_filename;
try {
hr = m_pConnTemp.CreateInstance(_T("ADODB.Connection"));
if (SUCCEEDED(hr))
hr = m_pConnTemp->Open((_bstr_t)strConn, _T(""), _T(""), -1);
OnOK();
} catch (_com_error e) {
AfxMessageBox(DisplayAdoError(m_pConnTemp));
}
CString CCommon::DisplayAdoError(_ConnectionPtr m_pConnection) {
long errorcount = m_pConnection->GetErrors()->GetCount();
_bstr_t add; CString ErrorMessage, temp;
for (short i=0; i<errorcount; i++) {
add = m_pConnection->GetErrors()->GetItem(_variant_t((short)i))->GetDescription();
temp = (char*)add;
ErrorMessage += temp;
}
return ErrorMessage;
}
遍歷 Errors 集合,串接所有 Description,避免只顯示第一個錯誤。
_variant_t fieldCount; VariantInit(&fieldCount);
MainFrame->m_pUserSet = MainFrame->m_commandptr->Execute(&fieldCount, NULL, adCmdUnknown);
if (!MainFrame->m_pUserSet->State) { // State 為 0 表示非 SELECT
View->ShowResult(fieldCount.lVal); // fieldCount.lVal 即影響列數
}
VariantClear(&fieldCount);
關鍵:Execute 第一個參數 RecordsAffected 為輸出參數,DML 回傳影響列數,DQL 回傳 Recordset。
listTable.ShowWindow(SW_SHOW);
listTable.DeleteAllItems();
// 清除舊欄位
for (i=0; i<listTable.GetHeaderCtrl()->GetItemCount(); i++)
listTable.DeleteColumn(0);
int fieldCount = Rsc->Fields->Count;
FieldPtr m_fieldCtl;
for (i=0; i<fieldCount; i++) {
m_fieldCtl = Rsc->Fields->GetItem(long(i));
int fieldLength = m_fieldCtl->DefinedSize * 10;
fieldLength = max(50, min(500, fieldLength));
fieldLength = max(fieldLength, m_fieldCtl->Name.length() * 12);
listTable.InsertColumn(i, m_fieldCtl->Name, LVCFMT_LEFT, fieldLength);
}
int nItem = 0; _variant_t varValue; _bstr_t bstrValue;
while (!Rsc->adoEOF) {
m_fieldCtl = Rsc->Fields->GetItem(long(0));
varValue = m_fieldCtl->Value;
if (varValue.vt == VT_NULL) bstrValue = _T(""); // 必須處理 NULL,否則轉換會拋出例外
else bstrValue = varValue;
nItem = listTable.InsertItem(0xffff, bstrValue);
for (i=1; i<fieldCount; i++) {
m_fieldCtl = Rsc->Fields->GetItem(long(i));
varValue = m_fieldCtl->Value;
if (varValue.vt == VT_NULL) bstrValue = _T("");
else bstrValue = varValue;
listTable.SetItem(nItem, i, 1, bstrValue, NULL, 0, 0, 0);
}
Rsc->MoveNext();
}
關鍵細節:
DefinedSize * 10,限制在 50~500 像素,並確保至少能顯示欄位名VT_NULL 顯式轉空字串,避免 _bstr_t 建構子拋出 _com_errorInsertItem(0xffff, ...) 追加至尾部// 執行 SQL
_CommandPtr m_pCommand;
m_pCommand.CreateInstance(__uuidof(Command));
m_pCommand->ActiveConnection = m_pConnection;
m_pCommand->CommandText = _T("SELECT * FROM DemoTable");
m_pRecordset = m_pCommand->Execute(NULL, NULL, adCmdText);
// 執行預存程序
m_pCommand->CommandText = _T("DemoProc");
m_pCommand->Execute(NULL, NULL, adCmdStoredProc);
// 如有參數,需用 _ParameterPtr 建立並 Append 至 m_pCommand->Parameters
// Stdafx.h 指定正確路徑
#import "msado15.dll" no_namespace rename("EOF", "adoEOF")
// 若路徑不同,請用完整路徑:C:\Program Files\Common Files\System\ADO\msado15.dll