总体来说VS有两种配置SQL Server的方式,一种是ADO,另一种是ODBC。这两种方式的查询我都有问题,查询到了结果数据不是乱码就是显示在list control上时值变了,我也不知道为什么。
以下ADO概念引用自 ADO数据库访问技术_lishan9133的博客-CSDN博客
ADO(active data object,活动数据对象),是一种基于COM(组件对象模型)的自动化接口技术,并以OLE DB(对象连接和镶入的数据库)为基础,经过OLE DB精心包装后的数据库访问技术,利用它可以快速的创建数据库应用程序。ADO提供了一组非常简单,将一般通用的数据访问细节进行封装的对象。由于ODBC数据源也提供了一般的OLE DB Privider,所以ADO不仅可以应用自身的OLE DB Privider,而且还可以应用所有的ODBC驱动程序。
1 引入ADO库文件,初始化COM组件
2 声明Connection实例对象,并连接(打开)数据库
3 利用连接对象 进行数据库操作
4 结束操作,关闭连接,释放连接对象
#import "C:/Program Files/Common Files/System/ado/msado15.dll" no_namespace rename("EOF","adoEOF")
这个路径下的msado.dll文件是已经存在的,不需要安装或者下载其他软件或库文件。有三点需要注意,也相当于四个问题吧。
第一:需要将外部文件引入到头文件中,在某个版本之后VS版本中pch.h就代替了那个s开头的头文件,这个无关紧要。
第二:引入这个文件路径的时候,VS编译器可能会报错,声称找不到这个文件,通过网上查找发现这个问题并不需要解决。也就是说出现这个BUG可能是编译器自己反应慢,这个错误在编译的时候也可以通过。
第三: no_namespace rename("EOF","adoEOF") 这条语句的作用是防止与其他库名中的EOF冲突。这里就不得不讲一讲EOF 和BOF了。BOF 指示当前记录位置位于记录集对象的第一个记录之前;EOF 指示当前记录位置位于记录集对象的最后一个记录之后。他们都是布尔值,即:只能为 True 或者 False。他们被用于判断记录指针是否越界,如果越界操作,程序运行会产生错误。如果没有打开记录集对象,BOF 和 EOF 都被设置为 True,RecordCount 属性值为 0;如果打开的记录集对象中至少包含一条记录,则第一条记录为当前记录,BOF 和 EOF 属性都为 False。
第四: 有些情况下会出现4996的错误,网上查找会有以下代码解决
项目属性->C/C++->SDL检查->关闭 ,然后在头文件定义之后再加上以下语句
#pragma warning(disable:4996)
HRESULT hr=CoInitialize(NULL);//ADO是COM组件,所以使用ADO连接数据库需要初始化COM组件 ASSERT(SUCCEEDED(hr)); //SUCCEEDED(hr)先判断COM是否初始化成功,如果不成功ASSERT的参数即为假,则会报告错误并终止程序
_ConnectionPtr pMyConnect; //连接对象指针 _RecordsetPtr pRecord; //记录集对象指针 _CommandPtr pCommand; //命令对象指针
Connection对象:它表示到数据库的连接,管理应用程序和数据库之间的通信。Command和Recordset对象都有一个ActiveConnection属性,该属性用来引用Connection对象。
Command对象:被用来处理重复执行的查询,或处理需要检查在存储过程调用中的输出或返回参数的值的查询。
Recordset对象:被用来获取数据。Recordset对象存放查询的结果,这些结果由数据的行(成为记录)和列(称为字段)组成。每一列都存放在Recordset的Fields集合中的一个Fields对象中。
try { pMyConnect.CreateInstance(__uuidof(Connection)); pRecord.CreateInstance(__uuidof(Recordset)); pMyConnect->Open("Provider=SQLOLEDB;Server=192.168.100.200;Database=TEST;uid=sa;pwd=123", "", "", adModeUnknown); } catch (_com_error& e) { AfxMessageBox(e.Description()+e.HelpFile()); return; }
这里创建了连接实例和记录集实例,并用调用了Open函数打开了数据库
第一个参数:连接字符串。这个字符串可以自己获取。在电脑的任意位置文本,并修改为以udl后缀的文件。
双击打开后 输入自己想要连接的数据库信息,然后再改回文本文件双击打开,第二行就是我们需要的内容了,下面随便给大家做个示例。如果想要显示密码那么就需要选中允许保存密码选项。
后面几个参数
adModeUnknown:缺省。当前的许可权未设置
adModeRead:只读
adModeWrite:只写
adModeReadWrite:可以读写
adModeShareDenyRead:阻止其它Connection对象以读权限打开连接
adModeShareDenyWrite:阻止其它Connection对象以写权限打开连接
adModeShareExclusive:阻止其它Connection对象以读写权限打开连接
adModeShareDenyNone:阻止其它Connection对象以任何权限打开连接
Connection对象除Open()方法外还有许多方法,我们先介绍Connection对象中两个有用的属性ConnectionTimeOut与State。ConnectionTimeOut用来设置连接的超时时间,需要在Open之前调用,例如:
m_pConnection->ConnectionTimeout = 5;///设置超时时间为5秒 m_pConnection->Open("Data Source=adotest;","","",adModeUnknown);
因为我是MFC程序,所以我就直接上完整代码了
//连接数据库 void CADOMFCDlg::OnBnClickedConnectButton() { HRESULT hr=CoInitialize(NULL);//ADO是COM组件,所以使用ADO连接数据库需要初始化COM组件 ASSERT(SUCCEEDED(hr)); //SUCCEEDED(hr)先判断COM是否初始化成功,如果不成功ASSERT的参数即为假,则会报告错误并终止程序 //_ConnectionPtr p(__uuidof(Connection)); //pMyConnect = p; //_RecordsetPtr pRst(__uuidof(Recordset));//定义记录集对象并实例化对象 //pRecord = pRst; try { pMyConnect.CreateInstance(__uuidof(Connection)); pRecord.CreateInstance(__uuidof(Recordset)); pMyConnect->Open("Provider=SQLOLEDB;Server=192.168.100.200;Database=TEST;uid=sa;pwd=123", "", "", adModeUnknown); } catch (_com_error& e) { AfxMessageBox(e.Description()+e.HelpFile()); return; } TODO: 在此添加额外的初始化代码 CRect rect; //showList.DeleteAllItems(); // 获取编程语言列表视图控件的位置和大小 showMessage.GetClientRect(rect); 为列表视图控件添加全行选中和栅格风格 showMessage.SetExtendedStyle(showMessage.GetExtendedStyle() | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES); // 为列表视图控件添加三列 showMessage.InsertColumn(0, _T("ID"), LVCFMT_CENTER, rect.Width() / 5); showMessage.InsertColumn(1, _T("姓名"), LVCFMT_CENTER, rect.Width() / 5); showMessage.InsertColumn(2, _T("性别"), LVCFMT_CENTER, rect.Width() / 5); showMessage.InsertColumn(3, _T("年龄"), LVCFMT_CENTER, rect.Width() / 5); showMessage.InsertColumn(4, _T("地址"), LVCFMT_CENTER, rect.Width() / 5); connectButton.EnableWindow(0); disConnectButton.EnableWindow(1); AfxMessageBox(L"数据库连接成功"); }
void CADOMFCDlg::OnBnClickedCloseButton() { try { pMyConnect->Close();//关闭数据库 pRecord.Release(); //释放记录集对象指针 pMyConnect.Release();//释放连接对象指针 pMyConnect = NULL; pRecord = NULL; ::CoUninitialize(); } catch (_com_error& e) { /*wchar_t buf[128]; swprintf(buf, L"错误描述:%s 错误帮助:%s", e.Description(), e.HelpFile()); AfxMessageBox(buf);*/ AfxMessageBox(e.Description() + e.HelpFile()); return; } connectButton.EnableWindow(1); disConnectButton.EnableWindow(0); AfxMessageBox(L"数据库关闭成功"); }
void CADOMFCDlg::OnBnClickedInsertButton() { // TODO: 在此添加控件通知处理程序代码 CString insertSql,ID,Name,Sex,Age,Address; GetDlgItemText(IDC_ID_EDIT,ID); if (ID == "") { AfxMessageBox(L"请输入ID"); return; } GetDlgItemText(IDC_NAME_EDIT, Name); GetDlgItemText(IDC_AGE_EDIT, Age); GetDlgItemText(IDC_ADDRESS_EDIT, Address); if (((CButton*)GetDlgItem(IDC_RADIO1))->GetCheck()) Sex = "man"; if (((CButton*)GetDlgItem(IDC_RADIO2))->GetCheck()) Sex = "woman"; int id = _ttoi(ID); int age = _ttoi(Age); insertSql.Format(L"insert into Student values('%d','%s','%s','%d','%s')",id, Name, Sex, age, Address); _RecordsetPtr pRecord; try { pRecord = pMyConnect->Execute((_bstr_t)insertSql, NULL, adCmdText); } catch (_com_error e) { AfxMessageBox(e.ErrorMessage()); return; } AfxMessageBox(L"插入数据成功"); }
这里我的变更条件就是ID name sex age address 可选项,目前只写了一个ID 的。
//更新数据 void CADOMFCDlg::OnBnClickedUpdateButton() { // TODO: 在此添加控件通知处理程序代码 if (pMyConnect == NULL) { AfxMessageBox(L"请先连接数据库后再操作"); return; } int nIndex = condition.GetCurSel(); CString con; CString ID, Name, Sex, Age, Address; condition.GetLBText(nIndex, con); //获取 需要修改数据 GetDlgItemText(IDC_ID_EDIT, ID); GetDlgItemText(IDC_NAME_EDIT, Name); GetDlgItemText(IDC_AGE_EDIT, Age); GetDlgItemText(IDC_ADDRESS_EDIT, Address); if (((CButton*)GetDlgItem(IDC_RADIO1))->GetCheck()) Sex = "man"; else if (((CButton*)GetDlgItem(IDC_RADIO2))->GetCheck()) Sex = "woman"; else Sex = ""; int id = _ttoi(ID); int age = _ttoi(Age); //获取 需要修改的条件 if (con == "ID") { CString updateSql1, updateSql2,updateSql3,updateSql4; if (ID == "") { AfxMessageBox(L"无法对空ID作出更新"); return; } else if ( Name == "" && Age == "" && Sex == "" && Address == "") { AfxMessageBox(L"未作出任何修改"); return; } CString selectID; selectID.Format(L"select * from Student where ID='%d'", _ttoi(ID)); try { pRecord = pMyConnect->Execute((_bstr_t)selectID, NULL, adCmdText); } catch (_com_error e) { AfxMessageBox(e.ErrorMessage()); return; } if (pRecord->adoEOF) { AfxMessageBox(L"无法对不存在的ID作出修改"); return; } if (Name != "") { updateSql1.Format(L"update Student set name ='%s' where ID='%d'", Name, _ttoi(ID)); try { pRecord = pMyConnect->Execute((_bstr_t)updateSql1, NULL, adCmdText); } catch (_com_error e) { AfxMessageBox(e.ErrorMessage()); return; } } if (Sex != "") { updateSql2.Format(L"update Student set sex ='%s' where ID='%d'", Sex, _ttoi(ID)); try { pRecord = pMyConnect->Execute((_bstr_t)updateSql2, NULL, adCmdText); } catch (_com_error e) { AfxMessageBox(e.ErrorMessage()); return; } } if (Age != "") { updateSql3.Format(L"update Student set age ='%s' where ID='%d'", Age, _ttoi(ID)); try { pRecord = pMyConnect->Execute((_bstr_t)updateSql3, NULL, adCmdText); } catch (_com_error e) { AfxMessageBox(e.ErrorMessage()); return; } } if (Address != "") { updateSql4.Format(L"update Student set address ='%s' where ID='%d'", Address, _ttoi(ID)); try { pRecord = pMyConnect->Execute((_bstr_t)updateSql4, NULL, adCmdText); } catch (_com_error e) { AfxMessageBox(e.ErrorMessage()); return; } } AfxMessageBox(L"根据ID数据修改成功"); } }
//删除数据 void CADOMFCDlg::OnBnClickedDeleteButton() { // TODO: 在此添加控件通知处理程序代码 if (pMyConnect == NULL) { AfxMessageBox(L"请先连接数据库后再操作"); return; } CString deleteSql,ID; GetDlgItemText(IDC_ID_EDIT, ID); if (ID =="") { AfxMessageBox(L"请输入ID后重试"); return; } CString selectID; selectID.Format(L"select * from Student where ID='%d'", _ttoi(ID)); try { pRecord = pMyConnect->Execute((_bstr_t)selectID, NULL, adCmdText); } catch (_com_error e) { AfxMessageBox(e.ErrorMessage()); return; } if (pRecord->adoEOF) { AfxMessageBox(L"无法删除不存在的ID"); return; } deleteSql.Format(L"delete from Student where ID ='%d'", _ttoi(ID)); try { pRecord = pMyConnect->Execute((_bstr_t)deleteSql, NULL, adCmdText); } catch (_com_error e) { AfxMessageBox(e.ErrorMessage()); return; } AfxMessageBox(L"数据删除成功"); }
//查询 void CADOMFCDlg::OnBnClickedSelectButton() { showMessage.DeleteAllItems(); _bstr_t sqlSelect = "select * from Student"; //查询Studnet表里的数据 if (pMyConnect == NULL) { AfxMessageBox(L"请连接数据库后再操作"); return; } int i = 0; wchar_t* id, * name, * sex, * address, * age; pRecord->Open(sqlSelect, pMyConnect.GetInterfacePtr(), adOpenDynamic, adLockOptimistic, adCmdText); //pRecord = pMyConnect->Execute(sqlSelect , NULL, adCmdText); //获取记录集 if (!pRecord->BOF) pRecord->MoveFirst(); else { AfxMessageBox(L"数据表为空"); return; } while (!pRecord->adoEOF) { id = (wchar_t*)(_bstr_t)pRecord->GetCollect(_T("ID")); name = (wchar_t*)(_bstr_t)pRecord->GetCollect(_T("name")); sex = (wchar_t*)(_bstr_t)pRecord->GetCollect(_T("sex")); age = (wchar_t*)(_bstr_t)pRecord->GetCollect(_T("age")); address = (wchar_t*)(_bstr_t)pRecord->GetCollect(_T("address")); showMessage.InsertItem(i, _T("")); showMessage.SetItemText(i, 0, id); //添加到list Control 中的第i行的第一列下 showMessage.SetItemText(i, 1, name); //添加到list Control 中的第i行的第二列下 showMessage.SetItemText(i, 2, sex); //添加到list Control 中的第i行的第三列下 showMessage.SetItemText(i, 3, age); //添加到list Control 中的第i行的第四列下 showMessage.SetItemText(i, 4, address); i += 1; //下次循环指向第2行 pRecord->MoveNext(); //移动到下一个记录 } pRecord->Close(); }
开放数据库连接(ODBC)是微软提出的数据库访问接口标准。用微软管阀的话来说就是:ODBC 是数据库 API 的规范。任何人都可以编写 ODBC 应用程序和驱动程序。使用 ODBC 的应用程序负责任何跨数据库功能。 例如,ODBC 不是异类联接引擎,也不是分布式事务处理器。 但是,由于它是与 DBMS 无关的,因此可用于生成此类跨数据库工具。
为了方便测试,我创建了一个最常见的student数据库和student信息表,如下图
1 在搜索栏搜索ODBC,这里我选择64位,最好与自己的VS编译版本和sql server版本一致。
2 点击添加
3 找到自己需要的数据库 数据源类型
4 编辑自己的数据源,这个在代码编写的时候会使用。 服务器填的是自己数据库所在的电脑IP地址,如果是本地就可以设置为127.0.0.1。
5 点击下一页 选择红框选项,并输入自己的sql server配置的sa 和密码
6 如果配置正确 就会进到下一个页面,默认下一步就好
7 点击测试数据源
8 出现下图就是数据源创建成功了,就可以准备代码了。
刚才说到配置正确才会进到下一步,如果sql server 安装失败或者配置失败就会出现下图类似的错误,至于解决方案,我的建议是重装,至于是装软件还是装机看个人运气。
选择SQL Server身份验证并输入自己设定的sa和密码。下方的数据库名可以选择自己创建的数据库,
这样在应用中就默认打开我们设置的数据库,也可以不设置。
配置成功后就可以在服务资源管理器中看到我们的数据库和表了
这里要知道一些概念和操作
本部分参考 以下前辈的博客(162条消息) 【ODBC】ODBC连接数据库详细说明_yzzheng_60125的博客-CSDN博客
应用程序运行后,为维护执行的状态,ODBC 管理器和ODBC 驱动程序中必须保持足够的控制信息。应用程序要求ODBC 管理器和ODBC 驱动程序为ODBC环境、每个连接以及每个SQL语句分配描述/控制信息存储空间,并返回指向各个存储区的句柄供其使用。
(1)环境句柄:整个ODBC上下文的根句柄。标识全程数据访问控制信息的内存结构,包括有效连接句柄以及当前活动连接句柄。ODBC将环境句柄定义为HENV类型的变量。应用程序使用单一的环境句柄,在连接到数据源以前必须申请该句柄。
(2)连接句柄:管理有关数据库会话的所有信息。连接句柄标识每个特定的连接信息的内存结构。ODBC将环境句柄定义为HDBC类型的变量。应用程序在连接数据源之前申请连接句柄。每个连接句柄与环境句柄有关,环境句柄上可以有多个与其有关的连接句柄。
(3)语句句柄:ODBC语句包括应用访问数据源的SQL语句和语句相关的管理信息,语句句柄标识每个语句管理信息的内存结构。ODBC将语句句柄定义为HSTMT类型的变量。应用程序在提交SQL请求之前也必须申请语句句柄。每个语句句柄与一个连接句柄有关,每个连接句柄上可以有多个与其有关的语句句柄。
这里大家也应该明白了,一个应用程序有一个环境句柄,用来给ODBC提供环境支持,在这个环境句柄上有多个连接句柄,用来管理数据库和标识数据库结构,每个环境句柄上又有多个语句句柄可以访问数据源。可以这样理解,但是肯定有偏差。
ODBC通过SQLAllocHandle来分配句柄
SQLRETURN ret;//返回信息
SQLHENV henv;//环境句柄 可以理解为申请并配置ODBC环境
SQLHDBC hdbc;//连接句柄 可以理解为申请数据库连接
SQLHSTMT hstmt;//语句句柄 可以理解为执行sql语句访问数据源
环境句柄 | SQLAllocHandle(SQL_HANDLE_ENV, NULL, &henv) |
连接句柄 | SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc) |
语句句柄 | SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt)或者SQLAllocStmt(hdbc, hstmt) |
SQLAllocHandle(SQL_HANDLE_ENV, NULL, &henv);//申请环境句柄 SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, SQL_IS_INTEGER);//设置环境句柄 SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);//申请数据库连接 ret = SQLConnect(hdbc, L"test", SQL_NTS, L"sa", SQL_NTS, L"你自己设置的密码", SQL_NTS); if ((ret == SQL_SUCCESS) || (ret == SQL_SUCCESS_WITH_INFO)) { AfxMessageBox(L"数据库成功打开"); } else { AfxMessageBox(L"打开数据库失败"); }
上述代码中SQLConnect 函数的作用就是连接数据源的数据库
参数含义: hdbc--连接句柄
test--数据源名称 ,根据个人添加的源名称
SQL_NTS--数据源名称的长度,用户名长度,密码长度
sa--用户名,根据个人设置
"你自己设置的密码"-- sa的密码
字符串前加L的含义:
文章参考前辈博客
字符串 前 L的含义_字符串前加l_whz_zb的博客-CSDN博客
一、 在字符串前加一个L作用: unicode字符集是两个字节组成的。L告示编译器使用两个字节的 unicode 字符集。
如 L"我的字符串" 表示将ANSI字符串转换成unicode的字符串,就是每个字符占用两个字节。
strlen("asd") = 3;
strlen(L"asd") = 6;
二、 _T宏可以把一个引号引起来的字符串,根据你的环境设置,使得编译器会根据编译目标环境选择合适的(Unicode还是ANSI)字符处理方式
如果你定义了UNICODE,那么_T宏会把字符串前面加一个L。这时 _T("ABCD") 相当于 L"ABCD" ,这是宽字符串。
如果没有定义,那么_T宏不会在字符串前面加那个L,_T("ABCD") 就等价于 "ABCD"
返回值:系统宏定义的防护值 这俩种情况就是成功
我个人认为释放句柄是有顺序的,因为一对多的关系,所以要反着释放,当然只是我个人的认为
释放语句句柄 | SQLFreeHandle(SQL_HANDLE_STMT, hstmt)或者SQLFreeStmt(hstmt, SQL_DROP) |
释放连接句柄 | SQLFreeHandle(SQL_HANDLE_DBC, hdbc)或者SQLDisconnect(hdbc)与SQLFreeConnect(hdbc) |
释放环境句柄 | SQLFreeHandle(SQL_HANDLE_ENV, henv)或者SQLFreeEnv(henv) |
//一些变量的定义在前文已经说明了 ret = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);//申请语句句柄 CString str1 = L"use student";//use 【你的数据库名称】 CString str2 = L"insert into Student values ('1','Bob', '18', '男', 'China')";//要执行的SQL语句 ret = SQLExecDirect(hstmt, (SQLWCHAR *)str1.GetBuffer(), SQL_NTS); ret = SQLExecDirect(hstmt, (SQLWCHAR*)str2.GetBuffer(), SQL_NTS); if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) { AfxMessageBox(L"插入数据成功"); } else { AfxMessageBox(L"插入数据失败"); }
效果
ret = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);//申请句柄 CString str1 = L"use student"; CString str2 = L"delete from student where name ='Bob'"; ret = SQLExecDirect(hstmt, (SQLWCHAR*)str1.GetBuffer(), SQL_NTS); ret = SQLExecDirect(hstmt, (SQLWCHAR*)str2.GetBuffer(), SQL_NTS); if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) { AfxMessageBox(L"数据删除成功"); } else { AfxMessageBox(L"数据删除失败,请检查表中是否有此数据"); }
ret = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);//申请句柄 CString str1 = L"use studnet"; CString str2 = L"update student set address ='济南' where name ='Bob'"; ret = SQLExecDirect(hstmt, (SQLWCHAR*)str1.GetBuffer(), SQL_NTS); ret = SQLExecDirect(hstmt, (SQLWCHAR*)str2.GetBuffer(), SQL_NTS); if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) { AfxMessageBox(L"数据修改成功"); } else { AfxMessageBox(L"数据删除失败,请检查表中是否有此数据"); }
引用部分以下前辈博客内容
(162条消息) 【ODBC】ODBC连接数据库详细说明_yzzheng_60125的博客-CSDN博客
SQLFetch函数的功能是将结果集的当前记录指针移至下一个记录;
SQLGetData函数的功能是提取结果集中当前记录的某个字段值。通常可以采用一个循环以提取结果集中所有记录的所有字段值,该循环重复执行SQLFetch和SQLGetData函数,直至SQLFetch函数返回SQL_NO_DATA_FOUND, 这表示已经到达结果集的末尾。
因为我用的是MFC程序 ,用到了 List control 控件 我的查询结果放在了这个控件上
message_list.DeleteAllItems(); ret = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);//申请句柄 CString str1 = L"use student"; CString str2 = L"select * from student"; ret = SQLExecDirect(hstmt, (SQLWCHAR*)str1.GetBuffer(), SQL_NTS); ret = SQLExecDirect(hstmt, (SQLWCHAR*)str2.GetBuffer(), SQL_NTS); int i = 0; if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) { while (SQLFetch(hstmt) != SQL_NO_DATA) { SQLWCHAR str1[10], str2[12], str3[20], str4[20],str5[20]; SQLLEN len_str1, len_str2, len_str3, len_str4,len_str5; SQLGetData(hstmt, 1, SQL_C_CHAR, str1, 10, &len_str1); //获取第一列数据 SQLGetData(hstmt, 2, SQL_C_CHAR, str2, 12, &len_str2); SQLGetData(hstmt, 3, SQL_C_CHAR, str3, 20, &len_str3); SQLGetData(hstmt, 4, SQL_C_CHAR, str4, 20, &len_str4); SQLGetData(hstmt, 5, SQL_C_CHAR, str5, 20, &len_str5); message_list.InsertItem(i, _T("")); message_list.SetItemText(i, 0, str1); //添加到list Control 中的第i行的第一列下 message_list.SetItemText(i, 1, str2); //添加到list Control 中的第i行的第二列下 message_list.SetItemText(i, 2, str3); //添加到list Control 中的第i行的第三列下 message_list.SetItemText(i, 3, str4); //添加到list Control 中的第i行的第四列下 message_list.SetItemText(i, 4, str5); //添加到list Control 中的第i行的第五列下 i++; } } else { AfxMessageBox(L"数据删除失败,请检查表中是否有此数据"); }
MFC部分代码
void CtestSqlServerDlg::OnBnClickedButton1() { // TODO: 在此添加控件通知处理程序代码 SQLAllocHandle(SQL_HANDLE_ENV, NULL, &henv);//申请环境句柄 SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, SQL_IS_INTEGER);//设置环境句柄 SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);//申请数据库连接 ret = SQLConnect(hdbc, L"test", SQL_NTS, L"sa", SQL_NTS, L"zyzb1234!", SQL_NTS); if ((ret == SQL_SUCCESS) || (ret == SQL_SUCCESS_WITH_INFO)) { AfxMessageBox(L"数据库成功打开"); //用于获取list control的尺寸 CRect rect; //获取控件尺寸 message_list.GetClientRect(rect); //风格设计 message_list.SetExtendedStyle(message_list.GetExtendedStyle() | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES); //创建表格字段 message_list.InsertColumn(0, _T("ID"), LVCFMT_CENTER, rect.Width() / 5, 0); message_list.InsertColumn(1, _T("姓名"), LVCFMT_CENTER, rect.Width() / 5, 1); message_list.InsertColumn(2, _T("性别"), LVCFMT_CENTER, rect.Width() / 5, 2); message_list.InsertColumn(3, _T("年龄"), LVCFMT_CENTER, rect.Width() / 5, 3); message_list.InsertColumn(4, _T("地址"), LVCFMT_CENTER, rect.Width() / 5, 4); btn_connect.EnableWindow(0); btn_disconnect.EnableWindow(1); } else { AfxMessageBox(L"打开数据库失败"); } /*if (!my_dataBase.Open(NULL, FALSE, FALSE, L"ODBC;DSN=test;UID=sa;PWD=123")) { AfxMessageBox(L"打开数据库失败"); } else { AfxMessageBox(L"数据库成功打开"); }*/ } //插入数据 void CtestSqlServerDlg::OnBnClickedButton2() { // TODO: 在此添加控件通知处理程序代码 ret = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);//申请语句句柄 CString str1 = L"use student";//use 【你的数据库名称】 CString str2 = L"insert into Student values ('1','Bob', '18', '男', 'China')";//要执行的SQL语句 ret = SQLExecDirect(hstmt, (SQLWCHAR *)str1.GetBuffer(), SQL_NTS); ret = SQLExecDirect(hstmt, (SQLWCHAR*)str2.GetBuffer(), SQL_NTS); if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) { AfxMessageBox(L"插入数据成功"); } else { AfxMessageBox(L"插入数据失败"); } /* CString insertSQL = L"insert into Student values ('1','zhangsan','man','18','China')"; my_dataBase.ExecuteSQL(insertSQL); */ } //删除数据 void CtestSqlServerDlg::OnBnClickedButton4() { ret = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);//申请句柄 CString str1 = L"use student"; CString str2 = L"delete from student where name ='Bob'"; ret = SQLExecDirect(hstmt, (SQLWCHAR*)str1.GetBuffer(), SQL_NTS); ret = SQLExecDirect(hstmt, (SQLWCHAR*)str2.GetBuffer(), SQL_NTS); if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) { AfxMessageBox(L"数据删除成功"); } else { AfxMessageBox(L"数据删除失败,请检查表中是否有此数据"); } } //修改数据 void CtestSqlServerDlg::OnBnClickedButton3() { ret = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);//申请句柄 CString str1 = L"use studnet"; CString str2 = L"update student set address ='济南' where name ='Bob'"; ret = SQLExecDirect(hstmt, (SQLWCHAR*)str1.GetBuffer(), SQL_NTS); ret = SQLExecDirect(hstmt, (SQLWCHAR*)str2.GetBuffer(), SQL_NTS); if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) { AfxMessageBox(L"数据修改成功"); } else { AfxMessageBox(L"数据删除失败,请检查表中是否有此数据"); } } //查询数据 void CtestSqlServerDlg::OnBnClickedButton5() { message_list.DeleteAllItems(); ret = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);//申请句柄 CString str1 = L"use student"; CString str2 = L"select * from student"; ret = SQLExecDirect(hstmt, (SQLWCHAR*)str1.GetBuffer(), SQL_NTS); ret = SQLExecDirect(hstmt, (SQLWCHAR*)str2.GetBuffer(), SQL_NTS); int i = 0; if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) { while (SQLFetch(hstmt) != SQL_NO_DATA) { SQLWCHAR str1[10], str2[12], str3[20], str4[20],str5[20]; SQLLEN len_str1, len_str2, len_str3, len_str4,len_str5; SQLGetData(hstmt, 1, SQL_C_CHAR, str1, 10, &len_str1); //获取第一列数据 SQLGetData(hstmt, 2, SQL_C_CHAR, str2, 12, &len_str2); SQLGetData(hstmt, 3, SQL_C_CHAR, str3, 20, &len_str3); SQLGetData(hstmt, 4, SQL_C_CHAR, str4, 20, &len_str4); SQLGetData(hstmt, 5, SQL_C_CHAR, str5, 20, &len_str5); message_list.InsertItem(i, _T("")); message_list.SetItemText(i, 0, str1); //添加到list Control 中的第i行的第一列下 message_list.SetItemText(i, 1, str2); //添加到list Control 中的第i行的第二列下 message_list.SetItemText(i, 2, str3); //添加到list Control 中的第i行的第三列下 message_list.SetItemText(i, 3, str4); //添加到list Control 中的第i行的第四列下 message_list.SetItemText(i, 4, str5); //添加到list Control 中的第i行的第五列下 i++; } } else { AfxMessageBox(L"数据删除失败,请检查表中是否有此数据"); } } //断开连接 void CtestSqlServerDlg::OnBnClickedButton6() { // TODO: 在此添加控件通知处理程序代码 //my_dataBase.Close(); SQLFreeHandle(SQL_HANDLE_STMT, hstmt);//释放语句 SQLFreeHandle(SQL_HANDLE_DBC, hdbc);//释放连接 SQLFreeHandle(SQL_HANDLE_ENV, henv);//释放环境 AfxMessageBox(L"数据库关闭成功"); /*btn_connect.EnableWindow(1); btn_disconnect.EnableWindow(0);*/ }