在现代的软件开发中,客户端动态访问数据库是一个常见的需求。这允许用户在不重新加载页面的情况下查询数据库、更新数据或填充下拉列表。本文将介绍如何使用CSQLQuery对象来实现这些功能。CSQLQuery是基于ATL/OLE DB库的一个动态类,它提供了多种示例来展示其用法。
要提交一个SQL语句,只需要实例化一个CSQLQuery对象,然后调用其ExecuteSQL成员函数,并将SQL字符串作为参数传递。例如:
CSQLQuery query(GetSession());
query.ExecuteSQL(
"SELECT MAX(UnitPrice) FROM Products"
);
检索数据同样简单。只需要定义一个变量,然后使用重载的>>操作符来获取数据。例如:
double dblUnitPrice = 0;
query >> dblUnitPrice;
注意,在这种情况下,需要关注数据映射。例如,SQL Server的数据类型int应该映射到C++的long类型。要将任何数据类型转换为字符串并避免映射,可以使用>操作符,如下所示:
CString str; query > str;
在这种情况下,不需要关心数据映射。所有类型的数据将自动映射到CString对象。
执行带参数的存储过程的示例代码如下:
double dblPar1 = 2.8, dblPar2 = 1.8;
CSQLQuery query(GetSession());
query << "EXECUTE sp_MyProcedure " << dblPar1 << ", " << dblPar2;
query.ExecuteSQL();
SQL更新语句的执行同样不复杂:
CSQLQuery query(GetSession());
query << "UPDATE Orders SET ShipName = 'MyName' WHERE EmployeeID = 5";
query.ExecuteSQL();
以下是一个填充列表框的示例。函数PopulateListBox根据参数dblMaxPrice的值填充列表框。列表框将填充单价超过dblMaxPrice的数据。可以将这个想法扩展到任何条件来检索数据。
void PopulateListBox(CListBox& box, double dblMaxPrice) {
box.ResetContent();
CSQLQuery query(GetSession());
query << "SELECT ProductID,ProductName FROM Products WHERE UnitPrice > " << dblMaxPrice;
if (!query.ExecuteSQL()) return;
while (!query.eof()) {
LONG lProductID = 0; CString strProductName;
query >> lProductID >> strProductName;
int idx = box.AddString(strProductName);
box.SetItemData(idx, lProductID);
}
}
以下示例展示了如何使用列和数据填充CListCtrl。
void CQueryView::ShowQuery(const CString strTableName) {
// 清除列表控件
m_listCtrl.DeleteAllItems();
while (m_listCtrl.DeleteColumn(0)) {}
CSQLQuery query(GetSession());
query << "SELECT TOP 100 * FROM " << strTableName;
if (!query.ExecuteSQL()) return;
// 显示列
int cols = query.GetColumnsCount();
for (int nCol = 0; nCol < cols; nCol++) {
CString strColName = query.GetColumnName(nCol);
m_listCtrl.InsertColumn(nCol, strColName, LVCFMT_LEFT, 80);
}
// 显示数据
int nItem = 0;
while (!query.eof()) {
CString str; query > str;
m_listCtrl.InsertItem(nItem, str);
for (int nSubItem = 1; nSubItem < cols; nSubItem++) {
CString str; query > str;
m_listCtrl.SetItemText(nItem, nSubItem, str);
}
nItem++;
}
}
CSQLQuery对象使用指向CSession类的指针。CSession对象代表在ATL库中定义的单个数据库访问会话。要为CDataSource创建一个新的CSession,只需实例化一个对象:
CDataSource m_datasource;
CSession m_session;
使用以下函数创建:
bool Connect(ATL::CDataSource* pDataSource, ATL::CSession* pSession) {
ASSERT(pDataSource);
CComBSTR bstrServer(m_strServerName);
CComBSTR bstrUser(m_strLoginName);
CComBSTR bstrPassword(m_strPassword);
CComBSTR bstrDatabase(m_strDatabaseName);
if (pSession && pSession->m_spOpenRowset != NULL)
pSession->m_spOpenRowset.Release();
CDBPropSet dbinit(DBPROPSET_DBINIT);
dbinit.AddProperty(DBPROP_AUTH_PASSWORD, bstrPassword);
dbinit.AddProperty(DBPROP_AUTH_PERSIST_SENSITIVE_AUTHINFO, false);
dbinit.AddProperty(DBPROP_AUTH_USERID, bstrUser);
dbinit.AddProperty(DBPROP_INIT_CATALOG, bstrDatabase);
dbinit.AddProperty(DBPROP_INIT_DATASOURCE, bstrServer);
dbinit.AddProperty(DBPROP_INIT_LCID, (long)1049);
dbinit.AddProperty(DBPROP_INIT_PROMPT, (short)4);
if (FAILED(pDataSource->Open(_T("SQLOLEDB.1"), &dbinit))) {
pDataSource->Close();
return false;
} else {
if (pSession && pSession->Open(*pDataSource) != S_OK) {
return false;
}
}
return true;
}
CSession* GetSession() {
return &m_session;
}