zoukankan      html  css  js  c++  java
  • C++ 通过ADO连接Oracle数据库

    背景

    接触C++以来,因为之前学的java做Web时经常要和数据库打交道,所以也就一直想用C++来操作数据库。之前也听过ODBC数据源的方法听说比较麻烦,C++用ADO的方法连接数据比较方便。

    下面就是具体的步骤和代码了。

    1.导入ADO的库

    使用ADO的话必须要导入它的库,这语句放到头文件.h中,因为我这里是用的MFC程序建的工程,所以我放在stdafx.h头文件中

    //导入ADO的库
    #import "C:\Program Files\Common Files\System\ado\msado15.dll" no_namespace rename("EOF","adoEOF")
      文件msado15.dll可以在你的电脑中的相应路径C:Program FilesCommon FilesSystemado找到;no_namespace 表示没有命名空间,可以不写不过后面的ADO对象要加上ADODB::引入;rename("EOF","adoEOF")是用adoEOF替换EOF ,如果你用到BOF的话也可以通过这种方式替换。

    2.在头文件中定义成员变量和成员函数

    在AdoDlg.h文件中:

    	//定义变量
    	 _ConnectionPtr m_conn; //连接智能指针
    	 _RecordsetPtr m_rec;//记录集智能指针
    	HRESULT hr;
    	 // //列表控件变量
    	 CListCtrl m_listCtrl;
    	 //函数
    	  bool AdoOpen(char* userName,char* pwd,char* conStr,char* errStr); //连接数据库
    	  //_RecordsetPtr AdoExucute(char* sqlStr); //执行sql语句,操作表
    	  bool AdoClose();//关闭数据库
    	  void InsertCol();//插入表头
    	  void GetRecordSet();//获得记录集
    	  void AdoQuery();//查询数据
    	  bool AdoAdd();//增加数据
    	  bool AdoUpdate();//修改数据
    	  bool AdoDelete();//删除数据

    3.在使用ADO前要初始化COM类库环境

    在AdoDlg.cpp文件中:

    a.在构造函数中初始化成员变量

    m_conn=NULL;

    b.在OnInitDialog()函数中

    //初始化COM类库
    	//CoInitialize返回的是HRESULT类型的值,返回S_OK(值为0)表示COM初始化成功,
    	// 返回S_FALSE(值为1)表示当前线程已经初始化过COM,所以返回S_OK或S_FALSE都是对的
    	/*if(FAILED(::CoInitialize(NULL))) 
    	{
    	MessageBox("初始化COM库失败");
    	return FALSE;
    	}*/
    	AfxOleInit();//MFC工程建议用AfxOleInit();
    //控制台建议用CoInitalize(),同时在Close函数或是析构函数中记得调用::CoUninitialize();卸载COM环境;

    //MFC工程建议用AfxOleInit();就行了。


    4.实现成员函数

     a .建立与数据库的连接

    //连接数据库
    bool CAdoDBDlg:: AdoOpen(char* userName,char* pwd,char* conStr,char* errStr)
    {
    	//捕获异常
    	try{
    
    		//创建Connection对象的一个实例
    		hr=m_conn.CreateInstance(_uuidof(Connection));///创建Connection对象
    
    		//通过用户名、密码以及连接字符串连接数据库
    		m_conn->Open(conStr,userName,pwd,NULL);
    
    	}catch(_com_error e)
    	{
    		MessageBox(e.ErrorMessage());
    	}
    	return TRUE;
    }

    b.获得查询的结果集

    //获取结果集
    void CAdoDBDlg::GetRecordSet()
    {
    		CString sql= "select * from MEMBERUSER"; //查询的SQL语句
    		
    		try{
    			m_rec.CreateInstance(_uuidof(Recordset));//创建结果集对象
    			m_rec->Open(_bstr_t(sql),m_conn.GetInterfacePtr(),adOpenDynamic,adLockOptimistic,adCmdText);
    		}catch(_com_error e)
    		{
    			MessageBox(e.Description());
    		}
    }
    aa. ADO中Recordset.Open()参数说明

    bb.ADO中数据类型的介绍variant、BSTR

    C.也可通过Execute函数来获得结果集

    //执行SQL语句
    _RecordsetPtr CAdoDBDlg::AdoExucute(char* sqlStr)
    {
    	try
    	{
    		if(m_conn==NULL)
    		{
    			MessageBox("请先连接数据库,再操作!");
    			return NULL;
    		}
    
    		_variant_t RecordsAffected;//此次操作的记录数
    		_RecordsetPtr PRecord;
    		//通过sql语句操作数据库并返回结果集指针
    		PRecord=m_conn->Execute(_bstr_t(sqlStr),&RecordsAffected,adCmdText);
    		 
    		/*int IntRecords = RecordsAffected.intVal;
    		CString StrRecords="0";
    		StrRecords.Format("此次操作了 %d 条数据.",IntRecords);
    		AfxMessageBox(StrRecords);*/
    
    		return PRecord;
    	}
    	catch (_com_error e)
    	{
    		MessageBox(e.ErrorMessage());
    	}
    
    }

    D.关闭函数

    //关闭数据库连接
    bool CAdoDBDlg::AdoClose()
    {
    	if(m_conn!=NULL)
    	{
    		m_conn->Close();//关闭连接
    		m_conn=NULL;
    		m_rec->Close();//关闭结果集
    		m_rec=NULL;
    
    		//::CoUninitialize();//卸载COM环境
    		
    	}
    
    	if(m_conn==NULL)
    		return TRUE;
    	else
    		return FALSE;
    }

    E.插入列表控件的表头和设置样式

    我用的是CListCtrl控件来显示查询到的数据,因为之前做类似Windows任务管理器时就是用的列表控件来显示数据,所以第一就想到了用它来显示表中的数据。

    //插入表头
    void CAdoDBDlg::InsertCol()
    {	//表的列名
    	 CString szItem[]={("记录数"),_T("ID"),_T("MemberName"),_T("AccounterNumber"),_T("Age"),_T("Gender"),_T("Birthday"),_T("RoleName"),_T("Pwd"),_T("Integal")};
    
    	 //设置列表控件的样式
    	 LONG lStyle;
    	 lStyle= GetWindowLong(m_listCtrl.m_hWnd,GWL_STYLE);//获得列表控件的当前样式
    	 lStyle &=~LVS_TYPEMASK; //清除显示方式位
    	 lStyle |=LVS_REPORT; //设置view属性的值为Report
    	 SetWindowLong(m_listCtrl.m_hWnd,GWL_STYLE,lStyle);
    	 
    	 //设置扩展风格--网格
    	 m_listCtrl.SetExtendedStyle(LVS_EX_GRIDLINES|LVS_EX_FULLROWSELECT);
    
    	//设置列表控件的表头
    	 int szLength = sizeof(szItem)/sizeof(szItem[0]);//求出数组长度
    
    	 for (int i=0;i<szLength;i++)
    	 {
    		 m_listCtrl.InsertColumn(i,szItem[i],LVCFMT_RIGHT,70,-1);//向控件中插入表头
    	 }
    
    
    }
    aa.遍历数据库中的所有表名和表的所有字段 第 6.7点


    5.///////////////////////////////////////////////增删改查

    a.查询

    void CAdoDBDlg::AdoQuery()
    {
    	//查询表中的数据
    	m_rec=AdoExucute("SELECT * FROM MEMBERUSER M;");
    }

    如果使用了GetRecordSet()方法这个函数可以不用,因为Recordset.Open(sql,.....)里面的sql语句就是查询表数据,就可以得到结果集

    b.增加数据

    //增加数据
    bool CAdoDBDlg::AdoAdd()
    {
    	if(m_conn==NULL)
    	{
    		MessageBox("数据库尚未连接,请连接后再操作!");
    		return FALSE;
    	}
    
    	CString strId1,strName,strAccounterName,strAge,strGender,strBirthday,strPwd,strIntegral,strRoleId;
    	int strId=12;
    	strName="中国人";
    	strAccounterName="zgr3";
    	strAge="100";
    	strGender="男";
            //获取系统当前时间
    	SYSTEMTIME st = {0};
    	GetLocalTime(&st);
    	strBirthday.Format("%d-%02d-%02d %02d:%02d:%02d",st.wYear,st.wMonth,st.wDay,st.wHour,st.wMinute,st.wSecond);
    		
    	strPwd="123456";
    	strIntegral="120";
    	strRoleId="2";
    
    	
    	GetRecordSet();//获取记录集
    
    	if(m_rec!=NULL)
    	{
    		UpdateData(TRUE);
    		for(int i=0;i<3;i++)
    			{
    			strAccounterName.Format("lyx%d",i);//主键唯一,防止重复
    			m_rec->AddNew();
    			m_rec->PutCollect(_variant_t("MEMBERID"),_variant_t((long)(strId+i)));  <span style="font-family: Arial, Helvetica, sans-serif;">//主键唯一,防止重复</span>
    			m_rec->PutCollect(_variant_t("MEMBERNAME"),_variant_t(strName));  
    			m_rec->PutCollect(_variant_t("ACCOUNTNUMBER"),_variant_t(strAccounterName));  
    			m_rec->PutCollect(_variant_t("AGE"),_variant_t(strAge));  
    			m_rec->PutCollect(_variant_t("GENDER"),_variant_t(strGender));  
    			m_rec->PutCollect(_variant_t("BIRTHDAY"),_variant_t(strBirthday));  
    			m_rec->PutCollect(_variant_t("PWD"),_variant_t(strPwd)); 
    			m_rec->PutCollect(_variant_t("MEMBER_INTEGRAL"),_variant_t(strIntegral));  
    			m_rec->PutCollect(_variant_t("ROLEID"),_variant_t(strRoleId));  
    			
    		}
    		m_rec->Update();
    
    		return TRUE;
    
    	}else
    	{
    		return FALSE;
    	}
    }
    注意:

    1.如果主键冲突就无法增加数据到数据库中,这个问题要注意,我就出现了这个问题,最后打断点运行才发现。

    2.如果你有的字段没有插入,数据库为空,那就查询不出来,比如我因为生日日期类型之前没有想到如何处理,就直接把

    m_rec->PutCollect(_variant_t("BIRTHDAY"),_variant_t(strBirthday));这句注释掉了,这样虽然可以正常插入到数据库中,但是当我点击查询按钮时,在数据库中这条数据及其以后的数据都无法在列表控件CListCtrl中显示出来。

    c.删除数据

    //删除数据
    bool CAdoDBDlg::AdoDelete()
    {
    	if(m_conn==NULL)
    	{
    		MessageBox("数据库尚未连接,请连接后再操作!");
    		return FALSE;
    	}
    	
    	GetRecordSet();
    	int pos =m_listCtrl.GetSelectionMark();//获得当前选中列表项索引,获得第几条数据
    
    	try
    	{
    		m_rec->Move(long(pos),vtMissing);//移到指定的第几条数据
    		m_rec->Delete(adAffectCurrent);//删除当前影响的数据
    		m_rec->Update();
    
    		return TRUE;
    	}
    	catch (_com_error e)
    	{
    		MessageBox(e.Description());
    		return FALSE;
    	}
    }

    D.修改数据

    //修改
    bool CAdoDBDlg::AdoUpdate()
    {
    	if(m_conn==NULL)
    	{
    		MessageBox("数据库尚未连接,请连接后再操作!");
    		return FALSE;
    	}
    
    	UpdateData(TRUE);
    
    	GetRecordSet();//获取记录集
    		
    	int pos =m_listCtrl.GetSelectionMark();//获得当前选中列表项索引
    	try{
    		
    		m_rec->Move(long(pos),vtMissing);//移到指定条记录
    		m_rec->PutCollect(_variant_t("gender"),_variant_t("女"));//修改指定字段的值
    		m_rec->Update();//更新到数据库
    
    		return TRUE;
    	}catch(_com_error e)
    	{
    		MessageBox(e.Description());
    		return FALSE;
    	}
    	
    
    }

    6.响应按钮函数

    //////////////////////////////////////按钮处理函数
    
    //建立连接
    void CAdoDBDlg::OnBnClickedBtnAdolink()
    {
    	// TODO: Add your control notification handler code here
    	if(m_conn==NULL)
    	{
    		////删除列表控件中的所有记录
    		int ColNum=m_listCtrl.GetHeaderCtrl()->GetItemCount();
    		for(int i=ColNum;i>=0;i--) //注意要从后面向前面删除,从前往后删会删不干净
    		{
    			m_listCtrl.DeleteColumn(i);
    		}
    		m_listCtrl.DeleteAllItems();//建立连接前删除控件内的所有数据
    
    
    		////连接oracle数据库的连接字符串
    		CString connStr="";
    		connStr.Format("Provider=OraOLEDB.Oracle.1;User ID=%s;Password=%s;Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=%s)(PORT=%s))(CONNECT_DATA=(SERVICE_NAME=%s)));Persist Security Info=False",
    			"XXX", "XXX", "127.0.0.1", "1521", "orcl");//User, Psw, Ip, Port, DataBaseName
    <span style="white-space:pre">		</span>// 上文  表示连接上一行
    		bool isConn=FALSE;
    		isConn=AdoOpen("XXX","XXX",(LPSTR)(LPCSTR)connStr,NULL);//建立连接
    		if(isConn)
    		{
    			MessageBox("连接oracle数据库成功!");
    
    			////插入表头
    			InsertCol();
    		}else
    		{
    			MessageBox("无法和数据库建立连接!");
    		}
    
    	}
    }
    //断开与数据库的连接
    void CAdoDBDlg::OnBnClickedBtnAdobreak()
    {
    	// TODO: Add your control notification handler code here
    
    	if(AdoClose())
    	{
    		MessageBox("数据库已断开连接!");
    	}else{
    		MessageBox("数据库断开失败!");
    	}
    }
    
    ////////////////////////////////////////////////////

    ////////////////////////////////////////////////////
    //查询数据库
    void CAdoDBDlg::OnBnClickedBtnQuery()
    {
    	m_rec.CreateInstance(_uuidof(Recordset));//创建记录实例
    
    	
    	m_listCtrl.DeleteAllItems();//查询前删除控件内的所有数据
    
    	//先求出表中一共有多少条数据
    	_RecordsetPtr recordSet;
    	recordSet = AdoExucute("select count(*) from memberUser");
    	variant_t count=0;
    	_variant_t index=long(0);
    	count = recordSet->GetCollect(index);//获得查询到的结果中的值
    	int num = count.intVal;//转换成int类型
    	// TODO: Add your control notification handler code here
    	//AdoQuery();//查询数据
    	GetRecordSet();//获取记录集
    
    	int RecordNum=0;//计数
    	while (!m_rec->adoEOF)
    	{
    		variant_t id,name,accounterNumber,age,gender,birthday,roleName,pwd,integral;
    
    		for (int i=0;i<num;i++)
    		{
    			id= m_rec->GetCollect("memberId");
    			name = m_rec->GetCollect("MEMBERNAME");
    			accounterNumber=m_rec->GetCollect("ACCOUNTNUMBER");
    			age=m_rec->GetCollect("AGE");
    			gender=m_rec->GetCollect("GENDER");
    			birthday=m_rec->GetCollect("BIRTHDAY");
    			roleName=m_rec->GetCollect("ROLEID");
    			pwd=m_rec->GetCollect("PWD");
    			integral=m_rec->GetCollect("MEMBER_INTEGRAL");
    
    			CString strid,strname,straccounterNumber,strage,strgender,strbirthday,strroleName,strpwd,strintegral,strRecordNum;
    			strid=(LPCSTR)_bstr_t(id);
    			strname=(LPCSTR)_bstr_t(name);
    			straccounterNumber=(LPCSTR)_bstr_t(accounterNumber);
    			strage=(LPCSTR)_bstr_t(age);
    			strgender=(LPCSTR)_bstr_t(gender);
    			strbirthday=(LPCSTR)_bstr_t(birthday);
    			strroleName=(LPCSTR)_bstr_t(roleName);
    			strpwd=(LPCSTR)_bstr_t(pwd);
    			strintegral=(LPCSTR)_bstr_t(integral);
    
    			RecordNum++;
    			strRecordNum.Format("%d",RecordNum);
    
    
    			//插入数据
    			m_listCtrl.InsertItem(i,strRecordNum);
    			m_listCtrl.SetItemText(i,1,strid);
    			m_listCtrl.SetItemText(i,2,strname);
    			m_listCtrl.SetItemText(i,3,straccounterNumber);
    			m_listCtrl.SetItemText(i,4,strage);
    			m_listCtrl.SetItemText(i,5,strgender);
    			m_listCtrl.SetItemText(i,6,strbirthday);
    			m_listCtrl.SetItemText(i,7,strroleName);
    			m_listCtrl.SetItemText(i,8,strpwd);
    			m_listCtrl.SetItemText(i,9,strintegral);
    
    			m_rec->MoveNext();
    		}
    
    	}
    	//AdoClose();//关闭连接
    }
    
    
    //删除
    void CAdoDBDlg::OnBnClickedBtnDelete()
    {
    	// TODO: Add your control notification handler code here
    	if(AdoDelete())
    	{
    		MessageBox("删除成功!");
    	}else
    	{
    		MessageBox("删除失败!");
    	}
    
    }
    
    
    
    //增加
    void CAdoDBDlg::OnBnClickedBtnAdd()
    {
    	// TODO: Add your control notification handler code here
    	// CAddDataDlg m_AddDateDlg;
    	 //if(m_AddDateDlg)
    		//m_AddDateDlg.DoModal();
    
    	if(AdoAdd())
    	{
    		MessageBox("增加成功!");
    	}else
    	{
    		MessageBox("增加失败!");
    	}
    
    
    }
    
    //修改
    void CAdoDBDlg::OnBnClickedBtnUpdate()
    {
    	// TODO: Add your control notification handler code here
    	
    	if(AdoUpdate())
    	{
    		MessageBox("更新成功!");
    	}else
    	{
    		MessageBox("更新失败!");
    	}
    }


    7.效果界面



    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    在Eclipse/STS里添加代码反编译器(.class)步骤
    关于页面添加字段
    关于jeesite Date和时间戳问题
    关于前端ajax通过实体类向后端传参报不存在问题
    引入字典
    关于添加主键
    简单的前后端分离项目 部署到 centos7
    Cenost7 Mysql5.7 安装 并打开远程访问
    npm install vue-cli -g 报错
    docker 笔记 docker 基础 docker 常用命令
  • 原文地址:https://www.cnblogs.com/lovelyx/p/4867094.html
Copyright © 2011-2022 走看看