使用ADO连接ODBC的一些记录以及问题
环境:VS2019 x86 Debug模式
连接方式:ODBC DSN连接
ADO使用流程:
(1)初始化COM库,引入ADO库定义文件
(2)用Connection对象连接数据库
(3)利用建立好的连接,通过Connection、Command对象执行SQL命令,或利用Recordset对象取得结果记录集进行查询、处理。
(4)使用完毕后关闭连接释放对象。
在VS中新建一个控制台程序,在预编译头文件中引入ADO动态链接库
预编译头文件 stdafx.h
内容如下
#pragma once
#pragma warning(disable:4146)
#import "C:\Program Files\Common Files\System\ADO\msado15.dll" named_guids rename("EOF","adoEOF"), rename("BOF","adoBOF")
#pragma warning(default:4146)
using namespace ADODB;
然后编译生成,在程序目录下会生成masdo.tlh 和 masdo15.tli两个文件,这两个文件是由c++编译器解析库文件生成的标准c++文件。
使用的头文件
#include "stdafx.h"
#include <iostream>
#include <odbcinst.h>
#include <atlstr.h>
问题1:此时发现一个问题,将编译环境切换到X64下,会报错,无法编译通过
然后在cpp文件中编写连接语句
这里有三个重要的指针
ADODB::_ConnectionPtr m_pConnection;
ADODB::_CommandPtr m_pCommand;
ADODB::_RecordsetPtr m_pRecordset;
分别表示连接集,命令集,记录集
_ConnectionPtr接口返回一个记录集或一个空指针。通常用于创建一个数据连接或者执行一条不返回任何结果的SQL语句,例如存储过程。
实际使用实例:
首先创建一个连接对象:
m_pConnection.CreateInstance(__uuidof(Connection));//创建一个连接对象
进行数据库连接:
先是使用直接连接:
CString strProvider = "Driver={TuntonSQL 1.01};UID=SYSDBA;PWD=SYSDBA;SERVER=127.0.0.1;Port=5138;Database=SYSTEM;CharSet=GBK;AutoCommit=TRUE";
m_pConnection->Open((_bstr_t)DSN, "SYSDBA", "SYSDBA", adModeUnknown);//打开连接
使用Open进行连接
问题2:此时进行连接的时候发现在Open会中断抛出异常。
判断:此时程序是x86 32位进行,数据源配置的是64位,于是去配置了一个32位的数据源,再次尝试
结果仍然错误。
此时的连接代码为
CString DSN= "Driver={TuntonSQL 1.01};UID=SYSDBA;PWD=SYSDBA;SERVER=127.0.0.1;Port=5138;Database=SYSTEM;CharSet=GBK;AutoCommit=TRUE";
try {
m_pConnection->Open((_bstr_t)DSN, "", "", adModeUnknown);//打开连接
}
catch(_com_error e)
{
CString errormessage;
std::cout << "错误信息:" << errormessage;
return;
}
此时发现这种为直接连接,不是对DSN数据源进行连接,于是修改连接方式为如下:
CString DSN="DSNmame";
m_pConnection->Open((_bstr_t)DSN, "UID", "PWD", adModeUnknown);
测试连接 没有报错
数据库操作:增删查改
查询数据:(使用Recordset进行连接)
m_pRecordset.CreateInstance(__uuidof(Recordset));
CString SQL = "select * from test_table3;";
CString vusername,id,age,sex,proc;
m_pRecordset->Open((_variant_t)SQL, m_pConnection.GetInterfacePtr(), adOpenStatic, adLockOptimistic, adCmdText);
while (!m_pRecordset->adoEOF)
{//两种获取结果集列的方法 列数和列名
id= m_pRecordset->GetCollect(_variant_t((long)0));//使用列数,从0开始
vusername = m_pRecordset->GetCollect("name");//使用列名
age= m_pRecordset->GetCollect("age");
sex= m_pRecordset->GetCollect("sex");
proc= m_pRecordset->GetCollect("proc");
//输出结果
std::wcout.imbue(std::locale("chs"));
std::wcout << id.GetString()<< vusername.GetString()<< age.GetString() << sex.GetString() << proc.GetString() <<std::endl;
m_pRecordset->MoveNext();
}
ps:使用connection进行连接
m_pRecordset = m_pConnection->Execute("select * from test_table3", &idr, adCmdText);
删除修改插入数据(使用connection进行连接)
使用语句
VARIANT idr;
VariantInit(&idr);
m_pConnection->Execute("delete from test_blob where id =1",&idr,adCmdText);
在删除数据时,刚开始未初始化VARIANT变量,执行失败,然后在初始化后执行,发现失败,检查发现是应为数据库的表因为绑定了外键,要保证一致性不能单表删除,于是换一个单独的表进行测试,成功。
ps:记录的键被其它表引用作为外键,不能更改或删除
此情况需要找到此键在何表作为外键,然后在此表处删除对应的字段后再进行删除即可
m_pConnection->Execute("delete from student where stuid =1", &idr, adCmdText);//先删除引为外键的表的行
m_pConnection->Execute("delete from test_table3 where id =1",&idr,adCmdText);//删除目标行
在使用update更新时,如果目标表中更新的属性为主键,并且是其他表的外键时,在没有使用级联的情况下,此时不能直接对他进行更新,只能先删除在插入一条数据。
问题:在对增删查改使用Recordset进行操作时,会抛出异常