ADO在这里就不细述了,直接讲解访问的过程。
#pragma once
#include<iostream>
#include <cassert>
#include <string>
#include <ATLComTime.h> //为了COleDateTime类引入
using namespace std;
//这是引入ADO动态链接库,默认的路径如下,如果不在默认地方,在这里需要另外指明位置
#import "c:\program files\common files\system\ado\msado15.dll" no_namespace rename("EOF", "adoEOF")
//以下类是为了其余人使用的方便做了一个简单的封装
class MyDateTime
{
public:
MyDateTime();
MyDateTime(COleDateTime oleDateTime);
MyDateTime(int year, int month, int day, int hour, int minute, int second);
~MyDateTime();
void SetDateTime(COleDateTime oleDateTime);
void SetMyDate(int year, int month, int day);
void SetMyTime(int hour, int minute, int second);
int GetYear();
int GetMonth();
int GetDay();
int GetHour();
int GetMinute();
int GetSecond();
void CurrentDateTime();
private:
COleDateTime m_oleDateTime;
};
class CppSQLDB
{
public:
~CppSQLDB();
//执行一些非查询类的语句,如insert delete update
void ExecuteDML(string strSql);
//执行带有返回记录集的查询类语句,insert into
void ExectueQuery(string strSql);
void SetFirstRow(); //这三个都是_RecordsetPtr对象拥有的函数,对外封装一层而已
bool Eof();
void NextRecord();
bool IsExist(string tablename, string fieldname, string value);
void GetIntValue(int nField, int &rInt);
void GetIntValue(string szField, int &rInt);
void GetFloatValue(int nField, float &rFloat);
void GetFloatValue(string szField, float &rFloat);
void GetStringValue(int nField, string &rString);
void GetStringValue(string szField, string &rString);
void GetCharArrValue(int nField, char *&rChar);
void GetCharArrValue(string szField, char *&rChar);
void GetDateTimeValue(int nField, MyDateTime &mdt);
void GetDateTimeValue(string szField, MyDateTime &mdt);
bool IsLegalUser(string loginname, string password);
bool IsExistUser(string loginname, string password);
public:
static CppSQLDB *m_sMe;
static CppSQLDB* GetMe()
{
if(m_sMe == NULL)
{
m_sMe = new(std::nothrow) CppSQLDB();
assert(m_sMe != NULL);
}
return m_sMe;
}
private:
//将其构造函数设置成私有的,防止外部程序私自建立单例模式的对象,从类本身出发控制了实例的数目
CppSQLDB();
_ConnectionPtr m_pConnection;
_CommandPtr m_pCommand;
_RecordsetPtr m_pRecordSet;
};
#include "CppSQLServer.h"
///
//MyDateTime类
//
MyDateTime::MyDateTime()
{
}
MyDateTime::MyDateTime(COleDateTime oleDateTime)
{
m_oleDateTime = oleDateTime;
}
MyDateTime::MyDateTime(int year, int month, int day, int hour, int minute, int second)
{
m_oleDateTime.SetDate(year, month, day);
m_oleDateTime.SetTime(hour, minute, second);
}
MyDateTime::~MyDateTime()
{
}
void MyDateTime::SetDateTime(COleDateTime oleDateTime)
{
m_oleDateTime = oleDateTime;
}
void MyDateTime::SetMyDate(int year, int month, int day)
{
m_oleDateTime.SetDate(year, month, day);
}
void MyDateTime::SetMyTime(int hour, int minute, int second)
{
m_oleDateTime.SetTime(hour, minute, second);
}
int MyDateTime::GetYear()
{
return m_oleDateTime.GetYear();
}
int MyDateTime::GetMonth()
{
return m_oleDateTime.GetMonth();
}
int MyDateTime::GetDay()
{
return m_oleDateTime.GetDay();
}
int MyDateTime::GetHour()
{
return m_oleDateTime.GetHour();
}
int MyDateTime::GetMinute()
{
return m_oleDateTime.GetMinute();
}
int MyDateTime::GetSecond()
{
return m_oleDateTime.GetSecond();
}
void MyDateTime::CurrentDateTime()
{
m_oleDateTime = COleDateTime::GetCurrentTime();
}
//**********************************************************************
//CppSQLServer类
//静态成员初始化
CppSQLDB* CppSQLDB::m_sMe = NULL;
CppSQLDB::CppSQLDB()
{
CoInitialize(NULL); //初始化COM
//初始化_ConnectionPtr指针对象实例
//在这个地方最好多用扑捉异常,因为一旦在整个访问过程中出了错就会出现一样的运行不下去,根本不知道哪里出错了
//使用异常后就会很快知道哪里出的问题
HRESULT hr;
//以下三个指针均为智能指针,所以不必担心有开辟没释放而导致的内存泄露问题
hr = m_pConnection.CreateInstance(__uuidof(Connection));
if(FAILED(hr))
{
cout<<"_ConnectionPtr对象指针实例化失败!!!"<<endl;
}
else
{
try
{
//连接语句,一般格式是固定的
//后面三个参数是 混合验证模式下登陆账号与密码(SQL SERVER 2008默认的是Windows验证模式,所以需要改) 还有要访问的数据库名
_bstr_t strConnect="Driver={sql server};server=127.0.0.1,1433;uid=supercell;pwd=supercell;database=ZHY;";
m_pConnection->Open(strConnect, "", "", adModeUnknown); //建立连接
}
catch(_com_error &e)
{
cout<<e.Description()<<endl;
}
}
//初始化_CommandPtr指针对象实例
hr = m_pCommand.CreateInstance(__uuidof(Command));
if(FAILED(hr))
{
cout<<"_CommandPtr对象指针实例化失败!!!"<<endl;
}
else
{
try
{
m_pCommand->ActiveConnection = m_pConnection; //为命令绑定连接对象
}
catch(_com_error &e)
{
cout<<e.Description()<<endl;
}
}
//初始化_RecordSetPtr指针对象实例
hr = m_pRecordSet.CreateInstance(__uuidof(Recordset));
if(FAILED(hr))
{
cout<<"_RecordSetPtr对象指针实例化失败!!!"<<endl;
}
//把这个数据库访问类做成了单例模式,单例模式的
m_sMe = this;
}
CppSQLDB::~CppSQLDB()
{
if (m_pConnection->State)
{
m_pConnection->Close();
}
if (m_pCommand->State)
{
m_pCommand->Release();
}
if (m_pRecordSet->State)
{
m_pRecordSet->Close();
}
}
void CppSQLDB::ExecuteDML(string strSql)
{
try
{
m_pCommand->CommandText = _bstr_t(strSql.c_str());
m_pCommand->Execute(NULL, NULL, adCmdText);
}
catch(_com_error &e)
{
cout<<e.Description()<<endl;
}
}
void CppSQLDB::ExectueQuery(string strSql)
{
try
{
m_pCommand->CommandText = _bstr_t(strSql.c_str());
m_pRecordSet = m_pCommand->Execute(NULL, NULL, adCmdText);
}
catch(_com_error &e)
{
cout<<e.Description()<<endl;
}
}
bool CppSQLDB::Eof()
{
return (bool)m_pRecordSet->adoEOF;
}
void CppSQLDB::SetFirstRow()
{
m_pRecordSet->MoveFirst();
}
void CppSQLDB::NextRecord()
{
m_pRecordSet->MoveNext();
}
bool CppSQLDB::IsExist(string tablename, string fieldname, string value)
{
char strSql[128] = { 0 };
sprintf_s(strSql, 128, "select count(*) from %s where %s = '%s'", tablename, fieldname, value);
_variant_t var;
int valueNums;
try
{
m_pCommand->CommandText = _bstr_t(strSql);
m_pRecordSet = m_pCommand->Execute(NULL, NULL, adCmdText);
m_pRecordSet->MoveFirst();
var = m_pRecordSet->GetCollect(_variant_t(long(0)));
var.vt = VT_I4;
valueNums = var;
}
catch(_com_error &e)
{
cout<<e.Description()<<endl;
}
if (valueNums > 0)
{
return true;
}
else
{
return false;
}
}
void CppSQLDB::GetIntValue(int nField, int &rInt)
{
_variant_t var;
try
{
var = (m_pRecordSet->GetCollect(_variant_t(long(nField))));
var.ChangeType(VT_I4); //转换数据类型为int
rInt = var;
}
catch(_com_error &e)
{
cout<<e.Description()<<endl;
}
}
void CppSQLDB::GetIntValue(string szField, int &rInt)
{
_variant_t var;
try
{
var = (m_pRecordSet->GetCollect(szField.c_str()));
var.ChangeType(VT_I4);
rInt = var;
}
catch(_com_error &e)
{
cout<<e.Description()<<endl;
}
}
void CppSQLDB::GetFloatValue(int nField, float &rFloat)
{
_variant_t var;
try
{
var = (m_pRecordSet->GetCollect(_variant_t(long(nField))));
var.ChangeType(VT_R4); //float
rFloat = var;
}
catch(_com_error &e)
{
cout<<e.Description()<<endl;
}
}
void CppSQLDB::GetFloatValue(string szField, float &rFloat)
{
_variant_t var;
try
{
var = (m_pRecordSet->GetCollect(szField.c_str()));
var.ChangeType(VT_R4);
rFloat = var;
}
catch(_com_error &e)
{
cout<<e.Description()<<endl;
}
}
void CppSQLDB::GetStringValue(int nField, string &rString)
{
try
{
rString = (char*)(_bstr_t)(m_pRecordSet->GetCollect(_variant_t(long(nField))));
//string类型转换形式不同
}
catch(_com_error &e)
{
cout<<e.Description()<<endl;
}
}
void CppSQLDB::GetStringValue(string szField, string &rString)
{
try
{
rString = (char*)(_bstr_t)(m_pRecordSet->GetCollect(szField.c_str()));
}
catch(_com_error &e)
{
cout<<e.Description()<<endl;
}
}
void CppSQLDB::GetCharArrValue(int nField, char *&rChar)
{
string strTemp;
try
{
strTemp = (char*)(_bstr_t)(m_pRecordSet->GetCollect(_variant_t(long(nField))));
strcpy_s(rChar, strTemp.length()+1, strTemp.c_str());
}
catch(_com_error &e)
{
cout<<e.Description()<<endl;
}
}
void CppSQLDB::GetCharArrValue(string szField, char *&rChar)
{
string strTemp;
try
{
strTemp = (char*)(_bstr_t)(m_pRecordSet->GetCollect(szField.c_str()));
strcpy_s(rChar, strTemp.length()+1, strTemp.c_str());
}
catch(_com_error &e)
{
cout<<e.Description()<<endl;
}
}
void CppSQLDB::GetDateTimeValue(int nField, MyDateTime &mdt)
{
_variant_t var;
COleDateTime dt;
try
{
var = (m_pRecordSet->GetCollect(_variant_t(long(nField))));
var.ChangeType(VT_DATE);
//ADO接口从数据库中返回的日期类型格式与ATL中COleDateTime正好匹配
dt = var;
mdt.SetDateTime(dt);
}
catch(_com_error &e)
{
cout<<e.Description()<<endl;
}
}
void CppSQLDB::GetDateTimeValue(string szField, MyDateTime &mdt)
{
_variant_t var;
COleDateTime dt;
try
{
var = (m_pRecordSet->GetCollect(szField.c_str()));
var.ChangeType(VT_DATE); //以上VT_****均为MSDN中已定义好的一些VT_TYPE类型
dt = var;
mdt.SetDateTime(dt);
}
catch(_com_error &e)
{
cout<<e.Description()<<endl;
}
}
bool CppSQLDB::IsLegalUser(string loginname, string password)
{
return IsExistUser(loginname, password);
}
//为了验证登陆用户的合法性
bool CppSQLDB::IsExistUser(string loginname, string password)
{
char strSql[128] = { 0 };
sprintf_s(strSql, 128, "select count(*) from UserInfor where uNo = '%s' and uPW = '%s'", loginname.c_str(), password.c_str());
_variant_t var;
int valueNums;
try
{
m_pCommand->CommandText = _bstr_t(strSql);
m_pRecordSet = m_pCommand->Execute(NULL, NULL, adCmdText);
m_pRecordSet->MoveFirst(); //移至数据集的第一行
var = m_pRecordSet->GetCollect(_variant_t(long(0))); //获取第一个字段的值(就是返回的目标记录行数)
var.vt = VT_I4;
valueNums = var;
}
catch(_com_error &e)
{
cout<<e.Description()<<endl;
}
if (valueNums > 0)//存在该目标用户
{
return true;
}
else
{
return false;
}
}
//**********************************************************
关于SQL SERVER 2008登陆验证模式的修改:点击打开链接
代码连带整个工程均在我的资源里,请需要的自行下载
以下为一个使用用例
#include "CppSQLServer.h"
int main()
{
//测试插入一条记录
// char szSql[128] = { 0 };
// MyDateTime mdt; //声明一个自定义日期时间类
// mdt.CurrentDateTime(); //获取当前时间,存储在内部变量中,无返回值
// //下面一条语句展示了如何获取当前的年月日等信息,返回的均是int
// sprintf_s(szSql, 128, "insert into UserInfor values('%s', '%s', '%d-%d-%d');", "HAHAHA", "HAHAHA", mdt.GetYear(), mdt.GetMonth(), mdt.GetDay());
// CppSQLDB::GetMe()->ExecuteDML(szSql);
//测试带有返回结果集的查询类
char szSql[128] = { 0 };
sprintf_s(szSql, 128, "select * from Student where Sage = '21';");
CppSQLDB::GetMe()->ExectueQuery(szSql); //传进查询语句,结果集保存在内部的ADO变量中,无返回
int no;
float age;
string name;
MyDateTime mdt;
CppSQLDB::GetMe()->SetFirstRow(); //在每一次新的查询后都要先设置记录集指针指向第一行记录,才可以遍历记录集
while (!CppSQLDB::GetMe()->Eof())
{
CppSQLDB::GetMe()->GetIntValue("Sno", no); //以字段名作为查询参数
CppSQLDB::GetMe()->GetStringValue(1, name); //以列索引(从0开始)作为查询参数
CppSQLDB::GetMe()->GetFloatValue("Sage", age);
CppSQLDB::GetMe()->GetDateTimeValue(5, mdt);
CppSQLDB::GetMe()->NextRecord(); //每获取一条记录后都要将记录集指针后移一行
cout<<no<<" "<<name<<" "<<age<<" "<<mdt.GetYear()<<"-"<<mdt.GetMonth()<<"-"<<mdt.GetDay()<<endl;
}
//测试登陆账号密码合法性
bool flag = CppSQLDB::GetMe()->IsLegalUser("zhaohaoyang", "zhaohaoyang");
if (flag)
{
cout<<"合法用户"<<endl;
}
else
{
cout<<"非法用户"<<endl;
}
return 0;
}