ADO连接SQL SERVER 2008数据库代码

时间:2021-04-10 21:50:44

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;
}