使用ADO编程接口 使用C++访问数据库

文章目录3.3 记录集对象
使用c++访问数据库(ADO) 1 创建数据库
【使用ADO编程接口使用C++访问数据库】新建查询—>粘贴下面eg代码—>执行—>刷新数据库—>创建成功
eg pxscj
create database pxscjgoUSE [pxscj]GO/****** Object:Table [dbo].[cjb]Script Date: 2017/9/25 5:25:57 ******/SET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE TABLE [dbo].[cjb]([学号] [char](6) NOT NULL,[课程号] [nchar](3) NOT NULL,[成绩] [int] NULL,CONSTRAINT [PK_cjb] PRIMARY KEY CLUSTERED ([学号] ASC,[课程号] ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY]GO/****** Object:Table [dbo].[kcb]Script Date: 2017/9/25 5:25:57 ******/SET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE TABLE [dbo].[kcb]([课程号] [char](3) NOT NULL,[课程名] [nchar](16) NOT NULL,[开课学期] [tinyint] NULL,[学时] [tinyint] NULL,[学分] [tinyint] NOT NULL) ON [PRIMARY]GO/****** Object:Table [dbo].[xsb]Script Date: 2017/9/25 5:25:57 ******/SET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE TABLE [dbo].[xsb]([学号] [char](6) NOT NULL,[姓名] [nchar](8) NOT NULL,[性别] [bit] NULL,[出生时间] [date] NULL,[专业] [nchar](12) NULL,[总学分] [int] NULL,[备注] [nvarchar](500) NULL,[照片] [varbinary](max) NULL,CONSTRAINT [PK_xsb] PRIMARY KEY CLUSTERED ([学号] ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY]GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'191301', N'101', 80)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'191301', N'102', 78)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'191301', N'206', 76)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'191302', N'102', 78)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'191302', N'206', 78)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'191303', N'101', 62)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'191303', N'102', 70)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'191303', N'206', 81)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'191304', N'101', 90)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'191304', N'102', 84)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'191304', N'206', 84)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'191306', N'101', 86)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'191306', N'102', 55)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'191306', N'206', 95)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'191307', N'101', 67)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'191307', N'102', 78)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'191307', N'206', 45)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'191308', N'101', 89)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'191308', N'102', 78)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'191309', N'101', 90)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'191309', N'102', 79)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'191309', N'206', 89)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'191310', N'101', 95)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'191310', N'206', 87)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'191311', N'101', 67)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'191311', N'102', 95)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'191311', N'206', 78)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'191313', N'101', 89)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'191313', N'102', 90)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'191313', N'206', 67)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'221301', N'101', 89)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'221301', N'102', 90)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'221301', N'206', 67)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'221302', N'101', 66)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'221302', N'102', 89)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'221302', N'206', 70)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'221303', N'102', 78)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'221303', N'206', 90)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'221304', N'101', 98)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'221304', N'102', 76)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'221304', N'206', 85)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'221306', N'101', 80)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'221306', N'102', 67)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'221306', N'206', 87)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'221310', N'101', 76)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'221310', N'102', 94)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'221310', N'206', 86)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'221316', N'101', 76)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'221316', N'102', 46)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'221316', N'206', 44)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'221318', N'101', 76)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'221318', N'206', 77)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'221320', N'101', 82)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'221320', N'102', 96)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'221320', N'206', 90)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'221321', N'101', 56)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'221321', N'102', 67)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'221321', N'206', 88)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'221341', N'101', 69)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'221341', N'102', 78)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'221341', N'206', 100)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'221341', N'208', 100)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'221341', N'209', 100)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'221341', N'210', 100)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'221341', N'212', 100)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'221341', N'301', 100)GOINSERT [dbo].[cjb] ([学号], [课程号], [成绩]) VALUES (N'221341', N'302', 100)GOINSERT [dbo].[kcb] ([课程号], [课程名], [开课学期], [学时], [学分]) VALUES (N'101', N'计算机基础', 1, 80, 5)GOINSERT [dbo].[kcb] ([课程号], [课程名], [开课学期], [学时], [学分]) VALUES (N'102', N'程序设计语言', 2, 68, 4)GOINSERT [dbo].[kcb] ([课程号], [课程名], [开课学期], [学时], [学分]) VALUES (N'206', N'离散数学', 4, 68, 4)GOINSERT [dbo].[kcb] ([课程号], [课程名], [开课学期], [学时], [学分]) VALUES (N'208', N'数据结构', 5, 68, 4)GOINSERT [dbo].[kcb] ([课程号], [课程名], [开课学期], [学时], [学分]) VALUES (N'209', N'操作系统', 6, 68, 4)GOINSERT [dbo].[kcb] ([课程号], [课程名], [开课学期], [学时], [学分]) VALUES (N'210', N'计算机原理', 5, 85, 5)GOINSERT [dbo].[kcb] ([课程号], [课程名], [开课学期], [学时], [学分]) VALUES (N'212', N'数据库原理', 7, 68, 4)GOINSERT [dbo].[kcb] ([课程号], [课程名], [开课学期], [学时], [学分]) VALUES (N'301', N'计算机网络', 7, 51, 3)GOINSERT [dbo].[kcb] ([课程号], [课程名], [开课学期], [学时], [学分]) VALUES (N'302', N'软件工程', 7, 51, 3)GOINSERT [dbo].[xsb] ([学号], [姓名], [性别], [出生时间], [专业], [总学分], [备注]) VALUES (N'191301', N'王林', 1, CAST(N'1990-02-10' AS Date), N'计算机', 60, N'bbb')GOINSERT [dbo].[xsb] ([学号], [姓名], [性别], [出生时间], [专业], [总学分], [备注]) VALUES (N'191302', N'程明', 1, CAST(N'1991-02-01' AS Date), N'计算机', 50, N'我是 191302')GOINSERT [dbo].[xsb] ([学号], [姓名], [性别], [出生时间], [专业], [总学分], [备注]) VALUES (N'191303', N'王燕', 0, CAST(N'1989-10-06' AS Date), N'计算机', 50, N'...')GOINSERT [dbo].[xsb] ([学号], [姓名], [性别], [出生时间], [专业], [总学分], [备注]) VALUES (N'191304', N'韦严平 ', 1, CAST(N'1990-08-26' AS Date), N'计算机', 50, N'...')GOINSERT [dbo].[xsb] ([学号], [姓名], [性别], [出生时间], [专业], [总学分], [备注]) VALUES (N'191306', N'李方方 ', 1, CAST(N'1990-11-20' AS Date), N'计算机', 50, N'...')GOINSERT [dbo].[xsb] ([学号], [姓名], [性别], [出生时间], [专业], [总学分], [备注]) VALUES (N'191307', N'李明', 1, CAST(N'1990-05-01' AS Date), N'计算机', 54, N'...')GOINSERT [dbo].[xsb] ([学号], [姓名], [性别], [出生时间], [专业], [总学分], [备注]) VALUES (N'191308', N'林一帆 ', 1, CAST(N'1989-08-05' AS Date), N'计算机', 52, N'...')GOINSERT [dbo].[xsb] ([学号], [姓名], [性别], [出生时间], [专业], [总学分], [备注]) VALUES (N'191309', N'张强明 ', 1, CAST(N'1994-08-11' AS Date), N'计算机', 50, N'...')GOINSERT [dbo].[xsb] ([学号], [姓名], [性别], [出生时间], [专业], [总学分], [备注]) VALUES (N'191310', N'张蔚', 0, CAST(N'1996-07-22' AS Date), N'计算机', 50, N'...')GOINSERT [dbo].[xsb] ([学号], [姓名], [性别], [出生时间], [专业], [总学分], [备注]) VALUES (N'191311', N'赵琳', 0, CAST(N'1995-03-18' AS Date), N'计算机', 50, N'...')GOINSERT [dbo].[xsb] ([学号], [姓名], [性别], [出生时间], [专业], [总学分], [备注]) VALUES (N'191313', N'严红', 0, CAST(N'1994-08-11' AS Date), N'计算机', 48, N'...')GOINSERT [dbo].[xsb] ([学号], [姓名], [性别], [出生时间], [专业], [总学分], [备注]) VALUES (N'191315', N'刘明仪 ', 1, CAST(N'1996-03-02' AS Date), N'计算机', 50, N'...')GOINSERT [dbo].[xsb] ([学号], [姓名], [性别], [出生时间], [专业], [总学分], [备注]) VALUES (N'221301', N'王敏', 1, CAST(N'1994-06-10' AS Date), N'通信工程', 42, N'...')GOINSERT [dbo].[xsb] ([学号], [姓名], [性别], [出生时间], [专业], [总学分], [备注]) VALUES (N'221302', N'王林', 1, CAST(N'1994-01-29' AS Date), N'通信工程', 40, N'...')GOINSERT [dbo].[xsb] ([学号], [姓名], [性别], [出生时间], [专业], [总学分], [备注]) VALUES (N'221303', N'王玉民 ', 1, CAST(N'1995-03-26' AS Date), N'通信工程', 42, N'...')GOINSERT [dbo].[xsb] ([学号], [姓名], [性别], [出生时间], [专业], [总学分], [备注]) VALUES (N'221304', N'马琳琳 ', 1, CAST(N'1995-02-10' AS Date), N'通信工程', 50, N'...')GOINSERT [dbo].[xsb] ([学号], [姓名], [性别], [出生时间], [专业], [总学分], [备注]) VALUES (N'221306', N'李计', 1, CAST(N'1995-09-20' AS Date), N'通信工程', 53, N'...')GOINSERT [dbo].[xsb] ([学号], [姓名], [性别], [出生时间], [专业], [总学分], [备注]) VALUES (N'221310', N'李红庆 ', 1, CAST(N'1994-05-01' AS Date), N'通信工程', 50, N'...')GOINSERT [dbo].[xsb] ([学号], [姓名], [性别], [出生时间], [专业], [总学分], [备注]) VALUES (N'221316', N'孙详欣 ', 1, CAST(N'1994-03-19' AS Date), N'通信工程', 50, N'...')GOINSERT [dbo].[xsb] ([学号], [姓名], [性别], [出生时间], [专业], [总学分], [备注]) VALUES (N'221318', N'孙研', 1, CAST(N'1995-10-09' AS Date), N'通信工程', 56, N'...')GOINSERT [dbo].[xsb] ([学号], [姓名], [性别], [出生时间], [专业], [总学分], [备注]) VALUES (N'221320', N'吴薇华 ', 1, CAST(N'1995-03-18' AS Date), N'通信工程', 48, N'...')GOINSERT [dbo].[xsb] ([学号], [姓名], [性别], [出生时间], [专业], [总学分], [备注]) VALUES (N'221321', N'刘燕敏 ', 1, CAST(N'1994-11-12' AS Date), N'通信工程', 50, N'...')GOINSERT [dbo].[xsb] ([学号], [姓名], [性别], [出生时间], [专业], [总学分], [备注]) VALUES (N'221341', N'罗林琳 ', 1, CAST(N'1995-01-30' AS Date), N'通信工程', 52, N'...')GOALTER TABLE [dbo].[cjb] ADDCONSTRAINT [DF_cjb_成绩]DEFAULT ((0)) FOR [成绩]GOALTER TABLE [dbo].[kcb] ADDCONSTRAINT [DF_kcb_开课学期]DEFAULT ((1)) FOR [开课学期]GOALTER TABLE [dbo].[kcb] ADDCONSTRAINT [DF_kcb_学时]DEFAULT ((0)) FOR [学时]GOALTER TABLE [dbo].[kcb] ADDCONSTRAINT [DF_kcb_学分]DEFAULT ((0)) FOR [学分]GOALTER TABLE [dbo].[xsb] ADDCONSTRAINT [DF_xsb_性别]DEFAULT ((1)) FOR [性别]GOALTER TABLE [dbo].[xsb] ADDCONSTRAINT [DF_xsb_专业]DEFAULT ('计算机') FOR [专业]GOALTER TABLE [dbo].[xsb] ADDCONSTRAINT [DF_xsb_总学分]DEFAULT ((0)) FOR [总学分]GO
2 测试是否成功连接数据库
(桌面 , 随便哪个位置)新建文本文档—>改拓展名.udl —>提供程序里面选择 OLE DBfor SQL —>下一步(连接)
测试数据库是否连接成功 , 填写
点击确定(中间的和下面两个)
注意:由于当时下面的确定我没有点 , 直接关闭了这个页面 , 导致打开打开的记事本文件里面没有显示
之后以记事本的方式打开这个udl文件
显示(之后会使用这个里面的连接串)
在这个连接串中 , Info 属性为 True 时表示在建立连接后仍然保存密码 , 一般取 False 即可。ID 和属性只有在上述数据库属性对话框中勾选“允许保存密码”时才会有。自己可以手工添加。pxscj 是我的数据库名。
3 开始写程序 3.1 程序框架
打开vs —> 创建空项目—>在项目中新建一个名为 main.cpp 的源文件 ,然后在这个文件中输入以下代码:
#import "c:\\Program Files\\Common Files\\System\\ADO\\msado15.dll" no_namespace rename("EOF", "EndOfFile")#include// wprintf#include // setlocaleint main(){setlocale(LC_ALL, "chs");CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);try{}catch (_com_error &err){wprintf(L"The application throws the error: %s\n", (wchar_t*)err.ErrorMessage());wprintf(L"Description = %s\n", (wchar_t*)err.Description());}CoUninitialize();return 0;}
点击调试—>选择开始执行(不调试)—>弹出黑框—>关闭
其中:
3.2 连接串和连接对象 创建连接对象
使用以下代码创建并打开一个连接对象。
将下面代码粘贴到上面代码try块
_bstr_t ConnStr("Provider = SQLOLEDB.1; Persist Security Info = False; User ID = sa; Password = 123456; Initial Catalog = pxscj; Data Source = XT-PC");_ConnectionPtr Conn(__uuidof(Connection));Conn->Open(ConnStr,"","",(long)0);
其中:
使用连接对象
在创建并打开了一个连接对象后 , 通过使用连接对象的方法 , 几乎可以将任意的 SQL 语句作为其参数 , 从而可以完成很多数据库的操作(增 、删 、查 、改)。比如:
Conn->Execute("UPDATE xsb SET 备注 = '外校互认学分课程', 总学分 = 总学分 + 3 WHERE 学号 = '231302'",NULL,(long)0);
对于查询这样的操作 , 则需要将连接对象方法的调用结果返回给一个记录集对象。
将上面代码粘贴至刚刚try里面(接着刚刚代码块)
点击调试—> 开始执行—>关闭
把刚刚udl用记事本打开的文件 , 红色框
复制,删贴到main.cpp文件里面try块
(把上面的连接串替换成自己的连接串)
调试—>执行 返回0 则运行成功
数据库的操作(增 、删 、查 、改)
打开数据库
选择pxscj—>—>选择前1000行
则会显示
在刚刚try代码里面 , 修改里面的数据
学号 = '191301'修改学号为191301的信息
调试—>开始执行
显示

使用ADO编程接口  使用C++访问数据库

文章插图
之后重新进行刚才的操作:
选择pxscj—>—>选择前1000行
你会发现数据发生改变(跟上面的表图对比)备注和总学分被修改
3.3 记录集对象
一个记录集对象代表了一些记录的集合 , 比如一个查询命令的执行结果。
一个sql语句执行结果就是一个集合 , ADO会把集合返回给一个记录集
3.3.1 创建记录对象
示例:
_RecordsetPtr RecordsetObj(__uuidof(Recordset)); //创建记录集对象//将sql执行结果返回记录集RecordsetObj中RecordsetObj = ConnObj->Execute("select * from xsb",NULL,(long)0);// 当这段sql语句执行成功后// GetString 将sql语句 执行为字符串wprintf 库函数wchar_t一个字符占用两个字节 宽字符串wprintf(L"%s\n", (wchar_t*)RecordsetObj->GetString(adClipString, long(-1), "\t", "\n", ""));
其中:
()使用
复制上面代码
粘贴至刚刚try块里面:(删除选中部分再粘贴)
将try块里面的Conn改为
然后:调试—>开始执行
3.3.2 使用记录集对象执行命令
如前所述 , 可以使用连接对象的方法执行命令 , 如果有返回的记录集 , 可以将这个记录集返回给一个记录集对象。使用 记录集对象的 Open 方法 , 也可以执行命令 , 但通常是有返回记录集的命令 , 比如执行语句。
使用open方法 , 通常执行命令有返回记录集
_bstr_t ConnStr("Provider = SQLOLEDB.1; Persist Security Info = False; User ID = sa; Password = 123456; Initial Catalog = pxscj; Data Source = XT-PC"); // 定义一个连接串_ConnectionPtr ConnObj(__uuidof(Connection));// 定义一个连接对象// 使用open方法ConnObj->Open(ConnStr,"","",NULL );_RecordsetPtr RecordsetObj(__uuidof(Recordset));// 定义记录集对象// 记录集获得整个学生信息RecordsetObj->Open( // 注意第一个个最后一个参数"xsb",// 参数:表名ConnObj.GetInterfacePtr(),adOpenForwardOnly,adLockReadOnly,adCmdTable);// 表类型// 表解释为一个字符串 , 作为字符串显示 wprintf(L"%s\n", (wchar_t*)RecordsetObj->GetString(adClipString, long(-1), "\t", "\n", ""));
在上述代码中 , 调用记录集对象的 Open 方法 , 注意其中的几个参数:
删除整个try块里面的代码
将上面代码粘贴至此处
重复之前一个操作:
把刚刚udl用记事本打开的文件 , 红色框
复制,粘贴到main.cpp文件里面try块
(把上面的连接串替换成自己的连接串)
注意:如果里面连接串有反斜线\ , 需要多加一个反斜线\  , 不然可能出现问题 。至于为什么加 , 我也不知道 , 老师讲的
调试—>开始执行
上面方法存在问题:列没有对齐 , 没有表头 , 需要改进
3.3.3 记录集的游标、当前记录、集合和字段对象
每个打开的记录集对象都有一个相应的游标 , 用于访问这个游标指向的一个记录。
记录集想象成一个二维表 , 游标就好像是一个指针 , 游标指向某一个记录 , 就是当前记录 。当我们访问记录集某一个记录 , 首先让游标指向记录 , 再操作 。
对于一个记录集的当前记录 , 使用这个记录集对象的属性(这是一个集合)可以访问这个当前记录中的各个字段对象。
记录集对象有属性有方法 。eg 面向对象中 , 成员变量相当于属性 , 成员函数相当于方法
属性:记录集字段属性
(字段集合 eg 姓名 学号 性别 分数) 记录集的字段集合(各个字段的集合)就是字段属性
每个字段对象均有一些诸如名字 、类型和值等属性。
对于一个集合类型的对象 , 比如 记录集对象的的属性 , 可以通过使用 (i) 方法访问其中的第 i+1 个元素(作为另一种选择 , 不是将一个集合元素的序号作为参数传递 , 而是传递一个字符串类型的字段名。) , 通过使用 Count 属性可以确定这个集合中包含的元素的个数。
游标的类型
一个记录集的对象的游标是有类型的 , 通常可在调用这个记录集的 Open 方法时指定 , 比如在前面的示例中 , 指定游标的类型为  , 这是一种资源开销最小的游标类型 , 但同时也是功能最弱的一种游标类型。这种游标类型正如它的名字所暗示的 , 它是一种只能向前滚动的游标 , 此外 , 这种游标没有敏感性 , 也就是说 , 在通过这种类型的游标访问记录集中的数据时 , 无法看到其它客户对这个记录集对应的基本表的修改。更多的游标的类型见。
使用ADO编程接口  使用C++访问数据库

文章插图
录集想象成一个二维表 , 游标就好像是一个指针
在下面的示例中 , 不再使用记录集对象的方法来显示记录集 , 而是先显示记录集的各个字段名作为标题 , 然后再每行显示一个记录。
// 创建并初始化连接对象_bstr_t ConnStr("Provider = SQLOLEDB.1; Persist Security Info = False; User ID = sa; Password = 123456; Initial Catalog = pxscj; Data Source = XT-PC"); _ConnectionPtr ConnObj(__uuidof(Connection));ConnObj->Open(ConnStr,"","",NULL);_RecordsetPtr RecordsetObj(__uuidof(Recordset));// 记录集open方法执行sql语句RecordsetObj->Open("select 学号, 姓名, 性别, 出生时间, 专业, 总学分, 备注 from xsb",ConnObj.GetInterfacePtr(),adOpenForwardOnly,adLockReadOnly,adCmdText);// 打印表头(粗略方法)printf("学号\t姓名\t性别\t出生时间\t专业\t总学分\t备注\n"); // 7个字段形成集合// 打印记录集各个部分//for循环 :对记录集遍历// 游标开始指向第一条记录 , 之后继续指向后面的// !RecordsetObj->EndOfFile不是指向最后一条记录// (wchar_t*)(_bstr_t) 两个强制性转换 , 字符类型 , 然后宽字符类型// RecordsetObj->Fields记录集对象RecordsetObj->Fields->GetItem获取字段 Value获取值GetItem返回一个字段getstring 直接获取所有 for (; !RecordsetObj->EndOfFile; RecordsetObj->MoveNext()){wprintf(L"%s\t", (wchar_t*)(_bstr_t)RecordsetObj->Fields->GetItem("学号")->Value); // 执行第一个for循环 , 获取学号字段值 , 打印wprintf(L"%s\t", (wchar_t*)(_bstr_t)RecordsetObj->Fields->GetItem("姓名")->Value);// 执行第二个for循环 , 获取姓名字段 , 打印wprintf(L"%s\t", (wchar_t*)(_bstr_t)RecordsetObj->Fields->GetItem("性别")->Value);// ...wprintf(L"%s\t", (wchar_t*)(_bstr_t)RecordsetObj->Fields->GetItem("出生时间")->Value);wprintf(L"%s\t", (wchar_t*)(_bstr_t)RecordsetObj->Fields->GetItem("专业")->Value);wprintf(L"%s\t", (wchar_t*)(_bstr_t)RecordsetObj->Fields->GetItem("总学分")->Value);wprintf(L"%s\t", (wchar_t*)(_bstr_t)RecordsetObj->Fields->GetItem("备注")->Value);printf("\n");}
上述代码跟之前相比多了表头 , 并没有什么改进 , 之后会进行修改
删除下图选中部分 , 将上述代码复制,粘贴到main.cpp文件里面try块删除部分
(第一行代码不用粘贴 , 粘贴了需要改成自己的连接串)
然后 , 调试—>开始执行
显示
或者(程序另外一个版本)
使用下面的代码 , 重复上面的操作
_bstr_t ConnStr("Provider = SQLOLEDB.1; Persist Security Info = False; User ID = sa; Password = 123456; Initial Catalog = pxscj; Data Source = XT-PC");_ConnectionPtr ConnObj(__uuidof(Connection));ConnObj->Open(ConnStr,"","",NULL);_RecordsetPtr RecordsetObj(__uuidof(Recordset));// 通过执行一个sql获得记录集对象RecordsetObj->Open("select 学号, 姓名, 性别, 出生时间, 专业, 总学分, 备注 from xsb",ConnObj.GetInterfacePtr(),adOpenForwardOnly,adLockReadOnly,adCmdText);// 打印表头// RecordsetObj->Fields->CountRecordsetObj记录集 , Fields方法 , Count个数(7 , 学号, 姓名, 性别...)// RecordsetObj->Fields->GetItem(i)字段集对象中第i个字段for (long i = 0; i < RecordsetObj->Fields->Count; i++){wprintf(L"%s\t", (wchar_t*)RecordsetObj->Fields->GetItem(i)->Name);}printf("\n");// 游标对记录集进行遍历// 第一个循环指向第一个记录 , 第二个指向第二个记录...for(;!RecordsetObj->EndOfFile; RecordsetObj->MoveNext())// 打印某行{for (long i = 0; i < RecordsetObj->Fields->Count; i++)// 打印某列 , 记录集列的个数 , 每行打印七次{wprintf(L"%s\t", (wchar_t*)(_bstr_t)RecordsetObj->Fields->GetItem(i)->Value);// 字段集序号i列引用之前通过字段名GetItem("专业")}printf("\n");}
执行结果
其中:
刚刚上面的代码存在的bug:
_bstr_t ConnStr("Provider = SQLOLEDB.1; Persist Security Info = False; User ID = sa; Password = 123456; Initial Catalog = pxscj; Data Source = XT-PC");_ConnectionPtr ConnObj(__uuidof(Connection));ConnObj->Open(ConnStr,"","",NULL);_RecordsetPtr RecordsetObj(__uuidof(Recordset));RecordsetObj->Open("select * from xsb",ConnObj.GetInterfacePtr(),adOpenForwardOnly,adLockReadOnly,adCmdText);COORDpos = { 0,0 };for (long i = 0; i < RecordsetObj->Fields->Count; i++){// SetConsoleCursorPosition 很重要的一个函数// 获取出一个字符串的宽度 , 像素SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos);// 显示字段名wprintf(L"%s", (wchar_t*)RecordsetObj->Fields->GetItem(i)->Name);// RecordsetObj->Fields->GetItem(i)->DefinedSize + 4; pos.X += (short)RecordsetObj->Fields->GetItem(i)->DefinedSize%16 + 4;}for (; !RecordsetObj->EndOfFile; RecordsetObj->MoveNext()){pos.X = 0;pos.Y++;for (long i = 0; i < RecordsetObj->Fields->Count; i++){SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos);if( RecordsetObj->Fields->GetItem(i)->Value.vt == VT_NULL )wprintf(L"Null");elsewprintf(L"%s", (wchar_t*)(_bstr_t)RecordsetObj->Fields->GetItem(i)->Value);pos.X += (short)RecordsetObj->Fields->GetItem(i)->DefinedSize % 16 + 4;}}
调试执行显示
最开始我的显示对齐的 , 但是最大化黑框就出现了问题 , 然后调整了窗口大小就好了(至于为什么 , 我还不知道)
3.3.4 修改记录
如果要修改某个记录的某个字段的数据 , 可以将一个语句发送给服务器。要完成这个工作 , 可以使用 连接对象的方法 , 可以使用 命令对象的方法 , 也可以使用 记录集对象的 Open 方法。尽管使用记录集对象的 Open 方法来执行一条不返回任何记录的 SQL 语句 , 不是通常的做法 , 但是确实可以这样做 , 比如:
RecordsetObj->Open("update xsb set 姓名='李四' where 学号='191301'",ConnObj.GetInterfacePtr(),adOpenForwardOnly,adLockReadOnly,adCmdText);
使用记录集对象确实可以修改数据 , 但不是像前面那样发送一个语句给服务器 , 而是给游标指向的当前记录的中的某个 Field 对象的 Value 属性赋值(等价于调用这个 Field 对象的方法)  , 然后调用这个 记录集对象的方法 , 将这个修改提交给服务器。
首先需要根据指定的条件 , 将记录集中的某个记录设置为当前记录 , 可以使用记录集的各种 Move 方法 , 或者使用查找方法。
在本例中 , 由于查找条件只涉及到一个列 , 因此可以使用 记录集的 Find 方法。此外 , 在打开记录集时 , 需要改变 Open 调用中的锁类型和游标类型 , 以支持查找和更新。
_bstr_t ConnStr("Provider = SQLOLEDB.1; Persist Security Info = False; User ID = sa; Password = 123456; Initial Catalog = pxscj; Data Source = XT-PC");_ConnectionPtr ConnObj(__uuidof(Connection));ConnObj->Open(ConnStr,"","",NULL);_RecordsetPtr RecordsetObj(__uuidof(Recordset));RecordsetObj->Open("select * from xsb",ConnObj.GetInterfacePtr(),adOpenStatic,adLockOptimistic,adCmdText);// 修改某某行某某列// 记录集对象查找方法 游标指向 某个特定记录 , 学号='191302' , 定位RecordsetObj->Find("学号='191302'",0, adSearchForward/*,vtMissing*/);if (!RecordsetObj->EndOfFile){// 将学号='191302' 姓名 修改只是在客户端修改还没有在服务器修改RecordsetObj->Fields->GetItem("姓名")->Value = "http://www.kingceram.com/post/王五";// Update将更新结果提交给服务器 , 服务器才被修改RecordsetObj->Update();}
有两种更新模式 , 一种是立即更新模式 , 另一种是批更新模式 , 前面的这个示例展示的只是立即更新模式 , 至于 批更新模式  , 详见 记录集的方法 和方法。
3.3.5 插入记录
使用记录集对象的方法可在这个记录集中追加一个新记录 , 且这个新纪录成为当前记录 , 然后设置这个记录的各个字段的值 , 最后调用这个记录集的方法 , 将对当前记录所做的更新提交到服务器。
_bstr_t ConnStr("Provider = SQLOLEDB.1; Persist Security Info = False; User ID = sa; Password = 123456; Initial Catalog = pxscj; Data Source = XT-PC");_ConnectionPtr ConnObj(__uuidof(Connection));ConnObj->Open(ConnStr,"","",NULL);_RecordsetPtr RecordsetObj(__uuidof(Recordset));// 获取记录集RecordsetObj->Open("select * from xsb",ConnObj.GetInterfacePtr(),adOpenStatic,adLockOptimistic,adCmdText);// 添加一条新记录 , 默认为当前记录RecordsetObj->AddNew();RecordsetObj->Fields->GetItem("学号")->Value = "http://www.kingceram.com/post/000000";RecordsetObj->Fields->GetItem("姓名")->Value = "http://www.kingceram.com/post/王五";RecordsetObj->Fields->GetItem("性别")->Value = http://www.kingceram.com/post/true;RecordsetObj->Fields->GetItem("出生时间")->Value = "http://www.kingceram.com/post/2000/01/01";RecordsetObj->Fields->GetItem("专业")->Value = "http://www.kingceram.com/post/计算机";RecordsetObj->Fields->GetItem("总学分")->Value = http://www.kingceram.com/post/0;RecordsetObj->Update();
注意 , 在上面的示例中 , 并没有新纪录的备注字段赋值 , 这是允许的 , 因为这个字段允许空值(NULL) 。此外 ,  方法还有一种带参数的用法(详见方法 主题) 。这种用户要求为指定两个类型的参数 , 这两个参数都是数组() , 一个用于指定字段名列表 , 一个用于指定值的列表。
_bstr_t ConnStr("Provider = SQLOLEDB.1; Persist Security Info = False; User ID = sa; Password = 123456; Initial Catalog = pxscj; Data Source = XT-PC");_ConnectionPtr ConnObj(__uuidof(Connection));ConnObj->Open(ConnStr,"","",NULL);_RecordsetPtr RecordsetObj(__uuidof(Recordset));RecordsetObj->Open("select * from xsb",ConnObj.GetInterfacePtr(),adOpenStatic,adLockOptimistic,adCmdText);_variant_t FieldName[6]= { "学号","姓名", "性别", "出生时间","专业","总学分" };_variant_t FieldValue[6] = { "000001", "王五", true,"2000/01/01", "计算机", 0 };SAFEARRAY *psaFieldName= SafeArrayCreateVector(VT_VARIANT, 0, 6);SAFEARRAY *psaFieldValue = http://www.kingceram.com/post/SafeArrayCreateVector(VT_VARIANT, 0, 6);for (long i = 0; i < 6; i++){SafeArrayPutElement(psaFieldName,&i, &FieldName[i]);SafeArrayPutElement(psaFieldValue, &i, &FieldValue[i]);}_variant_t FieldNameList, FieldValueList;FieldNameList.vt= VT_VARIANT | VT_ARRAY;FieldValueList.vt = VT_VARIANT | VT_ARRAY;FieldNameList.parray= psaFieldName;FieldValueList.parray = psaFieldValue;RecordsetObj->AddNew(FieldNameList, FieldValueList);
这种方法不需要调用  , 因为添加后 , ADO会自动调用它。
3.3.6 删除记录
调用 记录集对象的方法 可删除当前记录。在当前记录被删除后 , 它仍然是当前记录。此外 , 如果是立即更新模式 , 在调用方法后 , 无需再调用方法。
_bstr_t ConnStr("Provider = SQLOLEDB.1; Persist Security Info = False; User ID = sa; Password = 123456; Initial Catalog = pxscj; Data Source = XT-PC");_ConnectionPtr ConnObj(__uuidof(Connection));ConnObj->Open(ConnStr,"","",NULL);_RecordsetPtr RecordsetObj(__uuidof(Recordset));RecordsetObj->Open("select * from xsb",ConnObj.GetInterfacePtr(),adOpenStatic,adLockOptimistic,adCmdText);RecordsetObj->Find("学号='000000'", 0, adSearchForward/*,vtMissing*/);if (!RecordsetObj->EndOfFile){if (MessageBox(NULL, L"删除", L"删除学号为 000000 的学生记录", MB_OKCANCEL) == IDOK){RecordsetObj->Delete(adAffectCurrent);}}
3.3.7 记录集的排序
通过执行带有 order by 子句的查询命令 。可以得到有序的记录。通过设置记录集对象的 Sort 属性 , 也可以得到有序的记录。要使 Sort 属性起作用 , 必须在调用记录集对象的 Open 方法之前将这个记录集对象的属性设置为 (这个属性的缺省值为) , 否则在设置 Sort 属性 会导致一个错误。
_bstr_t ConnStr("Provider = SQLOLEDB.1; Persist Security Info = False; User ID = sa; Password = 123456; Initial Catalog = pxscj; Data Source = XT-PC");_ConnectionPtr ConnObj(__uuidof(Connection));ConnObj->Open(ConnStr,"","",NULL);_RecordsetPtr RecordsetObj(__uuidof(Recordset));RecordsetObj->CursorLocation = adUseClient;RecordsetObj->Open("select * from xsb",ConnObj.GetInterfacePtr(),adOpenStatic,adLockOptimistic,adCmdText);wprintf(L"%s\n\n", (wchar_t*)RecordsetObj->GetString(adClipString, long(-1), "\t", "\n", ""));RecordsetObj->Sort = "出生时间";wprintf(L"%s\n\n", (wchar_t*)RecordsetObj->GetString(adClipString, long(-1), "\t", "\n", ""));RecordsetObj->Sort = "专业, 总学分 desc";wprintf(L"%s\n\n", (wchar_t*)RecordsetObj->GetString(adClipString, long(-1), "\t", "\n", ""));RecordsetObj->Close();ConnObj->Close();
如果认为将会对某些字段执行较多次序的排序或查找操作 , 那么为这些字段建立索引会有助于提示这些操作的效率。这里所指的索引 , 并不是服务器中的某个基本表的索引 , 而是客户端的记录集的索引。在设置了一个记录集对象的为 , 然后打开这个记录集对象后 , 如果要为一个字段建立索引 , 那么将这个字段的属性(这是字段对象的一个动态属性)设置为 TRUE 即可。注意 , 仅当记录集的属性为时 , 这个记录集对象中的字段对象才有动态属性。
_bstr_t ConnStr("Provider = SQLOLEDB.1; Persist Security Info = False; User ID = sa; Password = 123456; Initial Catalog = pxscj; Data Source = XT-PC");_ConnectionPtr ConnObj(__uuidof(Connection));ConnObj->Open(ConnStr,"","",NULL);_RecordsetPtr RecordsetObj(__uuidof(Recordset));RecordsetObj->CursorLocation = adUseClient;RecordsetObj->Open("select * from xsb",ConnObj.GetInterfacePtr(),adOpenStatic,adLockOptimistic,adCmdText);RecordsetObj->Fields->GetItem("学号")->Properties->GetItem("Optimize")->Value = http://www.kingceram.com/post/TRUE;RecordsetObj->Sort = "学号 desc";wprintf(L"%s\n\n", (wchar_t*)RecordsetObj->GetString(adClipString, long(-1), "\t", "\n", ""));RecordsetObj->Close();ConnObj->Close();
3.3.8 记录集的过滤
通过执行带有 where 子句的查询命令 。可以得具有指定条件的记录。通过设置记录集对象的属性 , 也可以得到具有指定条件的记录。
_bstr_t ConnStr("Provider = SQLOLEDB.1; Persist Security Info = False; User ID = sa; Password = 123456; Initial Catalog = pxscj; Data Source = XT-PC");_ConnectionPtr ConnObj(__uuidof(Connection));ConnObj->Open(ConnStr,"","",NULL);_RecordsetPtr RecordsetObj(__uuidof(Recordset));RecordsetObj->CursorLocation = adUseClient;RecordsetObj->Open("select * from xsb",ConnObj.GetInterfacePtr(),adOpenStatic,adLockOptimistic,adCmdText);wprintf(L"%s\n\n", (wchar_t*)RecordsetObj->GetString(adClipString, long(-1), "\t", "\n", ""));RecordsetObj->Filter = "总学分 >= 52 and 姓名 like '王*'";wprintf(L"%s\n\n", (wchar_t*)RecordsetObj->GetString(adClipString, long(-1), "\t", "\n", ""));RecordsetObj->Filter = "";wprintf(L"%s\n\n", (wchar_t*)RecordsetObj->GetString(adClipString, long(-1), "\t", "\n", ""));RecordsetObj->Close();ConnObj->Close();
3.3.9 记录集的查找
前述的记录集的过滤操作起到了查找的作用 , 除此之外 , 可以使用