注册 登录
编程论坛 C++教室

求教C++连接数据库的方法

日寂 发布于 2015-12-13 00:11, 4432 次点击
似乎可以在代码中通过sql语句对数据库进行操作?求这样的方法教程!或者相关的书籍!
23 回复
#2
rjsp2015-12-13 11:46
ODBC
OTL
等等,甚至直接用对应数据库提供的APIs
#3
诸葛欧阳2015-12-15 22:39
查查官方文档肯定有这方面的API介绍
#4
wp2319572015-12-16 11:06
网络里  这种代码 很少  大概是保密吧   很多人发的数据库相关代码都不是完整的

我这里有一段能够通过编译运行的代码   

这段代码实现的功能就是输出了某个字段的全部记录

程序代码:

#include <stdio.h>
#include <windows.h>
#include <string.h>

#import "c:\Program Files\Common Files\System\ado\msado15.dll" no_namespace rename("EOF","adoEOF")   //引入ADO库

int main(void)
{
    _ConnectionPtr m_pConnection=NULL;
    CoInitialize(NULL);  //初始化com库
    HRESULT hr = m_pConnection.CreateInstance("ADODB.Connection");    //创建Connection对象
    if(SUCCEEDED(hr))  //创建数据库connection对象成功
    {
        hr = m_pConnection->Open("Driver={Microsoft dBase Driver (*.dbf)}","","",adModeUnknown);
        if(SUCCEEDED(hr))   //连接数据库字符串成功
        {
            _RecordsetPtr MySet;
            MySet.CreateInstance(__uuidof(Recordset));
            MySet->Open("SELECT * FROM 123",m_pConnection.GetInterfacePtr(),adOpenDynamic,adLockOptimistic,adCmdText);
            _variant_t Holder;
            while(!MySet->adoEOF)
            {
                Holder = MySet->GetCollect("XMMC");
                if(Holder.vt!=VT_NULL)
                    printf("%s\n",(char*)_bstr_t(Holder));
                MySet->MoveNext();
            }

        }
    }
    return 0;
}
#5
日寂2015-12-21 00:11
以下是引用wp231957在2015-12-16 11:06:09的发言:

网络里  这种代码 很少  大概是保密吧   很多人发的数据库相关代码都不是完整的

我这里有一段能够通过编译运行的代码   

这段代码实现的功能就是输出了某个字段的全部记录


#include <stdio.h>
#include <windows.h>
#include <string.h>

#import "c:\Program Files\Common Files\System\ado\msado15.dll" no_namespace rename("EOF","adoEOF")   //引入ADO库

int main(void)
{
    _ConnectionPtr m_pConnection=NULL;
    CoInitialize(NULL);  //初始化com库
    HRESULT hr = m_pConnection.CreateInstance("ADODB.Connection");    //创建Connection对象
    if(SUCCEEDED(hr))  //创建数据库connection对象成功
    {
        hr = m_pConnection->Open("Driver={Microsoft dBase Driver (*.dbf)}","","",adModeUnknown);
        if(SUCCEEDED(hr))   //连接数据库字符串成功
        {
            _RecordsetPtr MySet;
            MySet.CreateInstance(__uuidof(Recordset));
            MySet->Open("SELECT * FROM 123",m_pConnection.GetInterfacePtr(),adOpenDynamic,adLockOptimistic,adCmdText);
            _variant_t Holder;
            while(!MySet->adoEOF)
            {
                Holder = MySet->GetCollect("XMMC");
                if(Holder.vt!=VT_NULL)
                    printf("%s\n",(char*)_bstr_t(Holder));
                MySet->MoveNext();
            }

        }
    }
    return 0;
}

你好!
这个代码我调试的时候到Myset->Open();处的断点时发生了错误,提示:
Unhandled exception at 0x76D6D8A8 in Project1.exe: Microsoft C++ exception: _com_error at memory location 0x0018FA18.
这是因为什么呢?
#6
日寂2015-12-21 00:21
以下是引用wp231957在2015-12-16 11:06:09的发言:

网络里  这种代码 很少  大概是保密吧   很多人发的数据库相关代码都不是完整的

我这里有一段能够通过编译运行的代码   

这段代码实现的功能就是输出了某个字段的全部记录


#include <stdio.h>
#include <windows.h>
#include <string.h>

#import "c:\Program Files\Common Files\System\ado\msado15.dll" no_namespace rename("EOF","adoEOF")   //引入ADO库

int main(void)
{
    _ConnectionPtr m_pConnection=NULL;
    CoInitialize(NULL);  //初始化com库
    HRESULT hr = m_pConnection.CreateInstance("ADODB.Connection");    //创建Connection对象
    if(SUCCEEDED(hr))  //创建数据库connection对象成功
    {
        hr = m_pConnection->Open("Driver={Microsoft dBase Driver (*.dbf)}","","",adModeUnknown);
        if(SUCCEEDED(hr))   //连接数据库字符串成功
        {
            _RecordsetPtr MySet;
            MySet.CreateInstance(__uuidof(Recordset));
            MySet->Open("SELECT * FROM 123",m_pConnection.GetInterfacePtr(),adOpenDynamic,adLockOptimistic,adCmdText);
            _variant_t Holder;
            while(!MySet->adoEOF)
            {
                Holder = MySet->GetCollect("XMMC");
                if(Holder.vt!=VT_NULL)
                    printf("%s\n",(char*)_bstr_t(Holder));
                MySet->MoveNext();
            }

        }
    }
    return 0;
}

这是我根据作者叫启明工作室的《Visual C++ SQL Server数据库应用实例完全解析》里的基础代码改的:
程序代码:

#include<iostream>
#include<string>
using namespace std;

#import "c:\Program Files\Common Files\System\ado\msado15.dll" no_namespace rename("EOF","adoEOF") rename("BOF","adoBOF")

class ADOConn
{
    //定义变量
public:
    _ConnectionPtr m_pConnection;//添加一个纸箱Connection对象的指针
    _RecordsetPtr m_pRecordset;//添加一个指向Recordset对象的指针
   
//定义方法
public:
    ADOConn(){};
    virtual ~ADOConn(){};
    void OnInitADOConn();//初始化——连接数据库
    _RecordsetPtr& GetRecordSet(_bstr_t bstrSQL);//执行查询
    BOOL ExecuteSQL(_bstr_t bstrSQL);//执行sql语句,Insert Update_variant_t
    void ExitConnect();
};

void  ADOConn::OnInitADOConn()
{
    //初始化OLE/COM库环境
    ::CoInitialize(NULL);

    //创建Connection对象
    m_pConnection.CreateInstance("ADODB.Recordset");
    //设置连接字符串,必须是BSTR型或_bstr_t类型

    _bstr_t strConnect = "Provider=SQLOLEDB;Server=我的计算机;Database=Student;uid=sa;pwd=123456";

   
    /**********************************************************************************************/
    //                                 调试时在此处出错
    /**********************************************************************************************/
    m_pConnection->Open(strConnect, "", "", adModeUnknown);

    /**********************************************************************************************/
}

_RecordsetPtr& ADOConn::GetRecordSet(_bstr_t bstrSQL)
{
    //连接数据库,如果Connection对象为空,则重新连接数据库
    if (m_pConnection == NULL)
        OnInitADOConn();
    //创建记录集对象
    m_pRecordset.CreateInstance(__uuidof(Recordset));
    //取得表中记录
    m_pRecordset->Open(bstrSQL, m_pConnection.GetInterfacePtr(), adOpenDynamic, adLockOptimistic, adCmdText);

    return m_pRecordset;//返回记录集
}

//BOOL ADOConn::ExecuteSQL(_bstr_t bstrSQL)
//{
//    try
//    {
//        //是否已经连接数据库
//        if (m_pConnection == NULL)
//            OnInitADOConn();
//        m_pConnection->Execute(bstrSQL, NULL, adCmdText);
//
//        return true;
//    }
//    catch (_com_error e)
//    {
//        return false;
//    }
//}
//
//void ADOConn::ExitConnect()
//{    //关闭记录集和连接
//    if (m_pRecordset != NULL)
//        m_pRecordset->Close();
//    m_pConnection->Close();
//
//    ::CoUninitialize();//释放环境
//}

void main()
{
    string Sname;
    ADOConn m_AdoConn;
    m_AdoConn.OnInitADOConn();
    //设置select语句
    _bstr_t vSQL;
    vSQL = "select sname from Student";
    _RecordsetPtr m_pRecordset;
    m_pRecordset = m_AdoConn.GetRecordSet(vSQL);
    Sname = (LPCTSTR)(_bstr_t)m_pRecordset->GetCollect("sname");
    cout << Sname;
}

错误信息:
Unhandled exception at 0x76D6D8A8 in ex.exe: Microsoft C++ exception: _com_error at memory location 0x0018F784.
#7
wp2319572015-12-21 05:31
vs还是vc
#8
日寂2015-12-21 08:00
回复 7楼 wp231957
vs2013
#9
wp2319572015-12-21 08:09
我的是vs2010 + xp sp3  +dbf数据库

我没有sql环境  你用的sql是啥版本的  哪里下载  有空帮你测试一下
#10
日寂2015-12-21 09:49
回复 9楼 wp231957
sql server2012……哪里下载我忘了,直接百度随便找的……
请问这个可能是什么原因呢?

[此贴子已经被作者于2015-12-21 09:51编辑过]

#11
newdos2015-12-21 10:45
//把你调试出错的地方象下面用try catch包起来试试,看看有什么提示。
    try
    {
        m_pConnection->Open(strConnect, "", "", adModeUnknown);
    }
    catch(_com_error &e)
    {
            _bstr_t bstrSource(e.Source());  
            _bstr_t bstrDescription(e.Description());  
  
            printf("Error\n");  
            printf("\tCode = %08lx\n", e.Error());  
            printf("\tCode meaning = %s\n", e.ErrorMessage());  
            printf("\tSource = %s\n", (LPCSTR) bstrSource);  
            printf("\tDescription = %s\n", (LPCSTR)bstrDescription);  
    }
#12
日寂2015-12-21 16:22
回复 11楼 newdos
Error
Code = 800a0e79
Code meaning = Unknown error 0x800AOE79
Source = ADODB.Connection
Description = 对象打开时,不允许操作

不允许操作……是说我连接数据库使用的账号有问题吗?
#13
newdos2015-12-21 16:58
大致是你提供的链接字符串有问题吧,如果密码账户木有问题的话,多半是server那个地方有问题,服务器那里一般填ip地址,或是点.来替代本机sql服务。你可以试试。记得一般这个字符串可以在odbc配置测试连接那个对话框时会显示,直接复制到自己程序里就行了,反正俺的印象中server=这里不会是“我的电脑“这种字符串。很久没用微软的sql了,有版权的东西。

[此贴子已经被作者于2015-12-21 17:14编辑过]

#14
日寂2015-12-21 17:58
回复 13楼 newdos
我以为server=PC名……
请问用点.来代替是把server=<...>整个替换成'.'还是server=.呢?
#15
newdos2015-12-21 18:10
以下是引用日寂在2015-12-21 17:58:55的发言:

我以为server=PC名……
请问用点.来代替是把server=<...>整个替换成'.'还是server=.呢?


server=.
server=127.0.0.1   貌似本机ip地址是这种样子,意思都一样。确保链接的数据库是Student存在,一般都可以连通。自己试试吧.  ado好像都过时了,被取代了。。那种代码并不通用。

[此贴子已经被作者于2015-12-21 18:14编辑过]

#16
日寂2015-12-21 19:31
回复 15楼 newdos
还是不行,同样的错误信息……
数据库Student确保存在
#17
wmf20142015-12-21 19:43
回复 16楼 日寂
你可以先在本机建立一个sql server的odbc链接,以确定本机sql server可用。
#18
日寂2015-12-21 21:35
回复 17楼 wmf2014
是说“管理工具”的 “ODBC数据源”吗?如果是的话我使用的Student数据库已经添加成功了
#19
newdos2015-12-21 22:27
明天测试一下ado连mdb,vs过期不能用了,无法测试sql,等版主测试吧.。不行就用odbc连接。

mdb测试结果:

#include <stdio.h>
#include <assert.h>
#include <tchar.h>

// TODO: 在此处引用程序需要的其他头文件
#import "c:\program files\common files\system\ole db\oledb32.dll" no_namespace
#import "c:\program files\common files\system\ado\msado15.dll" no_namespace rename("EOF", "adoEOF")

void main()
{
    IDataSourceLocatorPtr Idslp = NULL;
    _ConnectionPtr ado_conn = NULL;
    _RecordsetPtr  ado_rs = NULL;
   
    ::CoInitialize(NULL);
   
    Idslp.CreateInstance(__uuidof(DataLinks));
    ado_conn = Idslp->PromptNew(); //弹出数据库源选择对话框
   
    if(ado_conn != NULL){
        
        printf("ConnectString : %s\n", (char *)ado_conn->ConnectionString); //输出连结字符串
    }
   
    try{
        HRESULT hr = ado_conn->Open("", "", "", -1);
        if(SUCCEEDED(hr))
            printf("open successful\n");
        
        ado_rs.CreateInstance(__uuidof(Recordset));
        ado_rs->Open("SELECT * FROM student",ado_conn.GetInterfacePtr(),
            adOpenDynamic,adLockOptimistic,adCmdText);

        _variant_t Holder;
        while(!ado_rs->adoEOF)
        {
            Holder = ado_rs->GetCollect("pass"); //查询字段
            if(Holder.vt!=VT_NULL)
                printf("%s\n",(char*)_bstr_t(Holder));
            ado_rs->MoveNext();
        }
    }
    catch(_com_error &e)
    {
        _bstr_t bstrDescription(e.Description());
        printf("\tDescription = %s\n", (LPCSTR)bstrDescription);
    }
   
    ado_rs.Release();
    if(ado_conn->State) ado_conn->Close();
    ado_conn.Release();
    Idslp.Release();
   
    ::CoUninitialize();
}

-------------------------------------------------------------------------
ConnectString : Provider=Microsoft.Jet.OLEDB.4.0;Data Source=F:\VC6_prg\test12\m
ydb.mdb;Persist Security Info=False
open successful
123
456
是你
Press any key to continue

可以联结上,并自动显示连结字符串,你根据弹出的选择数据源框进行SQL连结测试,完了就会出现不同的字符串。拷下来就好了。

不过vs编译会出现4192警告,解释办法查msdn, Com代码看着很蛋疼。

[此贴子已经被作者于2015-12-22 13:09编辑过]

#20
wp2319572015-12-22 13:49
这是我在网络里找到的一段言论  我觉得他可能是对的  因为我用第二种方式 连接成功(第一种 死机  第三种没有测试  我的sql登陆方式属于第二种)

程序代码:

一、连接SQL SERVER的第一种连接字串:
是针对数据库身份验证模式为”SQL SERVER 和 windows“而言,
连接字串为:
CString strConn;
strConn = ”Provider = SQLOLEDB.1;\
Persist Security Info = true;\
User ID = sa;\
Password=123456;\
Initial Catalog = tempdb;\
Data Source = 127.0.0.1”;
(包含 6 项,有用户名和密码,数据库名,服务器名(服务器名可以是网络上的,此时是一个IP地址))

二、连接SQL SERVER的第二种连接字串:
针对身份验证模式为“仅 windows”,
连接字串为:
strConn= “
Provider = SQLOLEDB.1;\
Integrated Security=SSPI;\
Persist Security Info =false;\
Initial Catalog = tempdb;\
Data Source = (local)”;
(包含 5 项,因为已经有windows验证了,所以不再需要用户名和密码,如果是本机的SQL SERVER,那么服务器名可写为(local))

三、连接SQL SERVER的第三种连接字串:
仅针对ODBC的连接方式,
连接字串为:
strConn= “
Provider = SQLOLEDB;\
Server = (local);\
Database = tempdb;\
uid = sa;\
pwd=12345;"



附上我的成功代码 : xp+sp3  vs2010  sql2005  测试成功

程序代码:

#include <stdio.h>
#include <windows.h>
#include <string.h>

#import "c:\Program Files\Common Files\System\ado\msado15.dll" no_namespace rename("EOF","adoEOF")   //引入ADO库

int main(void)
{
    _ConnectionPtr m_pConnection=NULL;
    CoInitialize(NULL);  //初始化com库
    HRESULT hr = m_pConnection.CreateInstance("ADODB.Connection");    //创建Connection对象
    if(SUCCEEDED(hr))  //创建数据库connection对象成功
    {
        _bstr_t strConnect = "Provider = SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info =false;Initial Catalog = student;Data Source = (local)";
        hr = m_pConnection->Open(strConnect,"","",adModeUnknown);
        if(SUCCEEDED(hr))   //连接数据库字符串成功
        {
            _RecordsetPtr MySet;
            MySet.CreateInstance(__uuidof(Recordset));
            MySet->Open("SELECT * FROM base",m_pConnection.GetInterfacePtr(),adOpenDynamic,adLockOptimistic,adCmdText);
            _variant_t Holder;
            while(!MySet->adoEOF)
            {
                Holder = MySet->GetCollect("xm");
                if(Holder.vt!=VT_NULL)
                    printf("%s\n",(char*)_bstr_t(Holder));
                MySet->MoveNext();
            }
        }
    }
    return 0;
}


[此贴子已经被作者于2015-12-22 13:52编辑过]

#21
wp2319572015-12-22 13:59
在桌面上新建一个文本文档   默认名字为  新建 文本文档.txt   改名为  新建 文本文档.udl   然后双击运行它   选择合适的数据库引擎

并成功的测试连接  然后在使用记事本打开这个udl文件  里面会有现成的链接字符串
#22
wp2319572015-12-22 14:16
以下是引用wp231957在2015-12-22 13:59:10的发言:

在桌面上新建一个文本文档   默认名字为  新建 文本文档.txt   改名为  新建 文本文档.udl   然后双击运行它   选择合适的数据库引擎

并成功的测试连接  然后在使用记事本打开这个udl文件  里面会有现成的链接字符串



使用这种办法  测试accdb 数据库连接  字符串是这样的  

Provider=Microsoft.ACE.OLEDB.12.0;Data Source=d:\wp.accdb;Persist Security Info=False

大约和 19  楼是一个样子的吧
#23
日寂2015-12-22 16:16
回复 20楼 wp231957
非常感谢!总算是成功了!我第一种第二种都能成功!
#24
日寂2015-12-22 16:19
回复 19楼 newdos
用版主给的格式已经能用了!谢谢这几天的帮忙!
1