VC里怎么同时搞定oracle和SQL Server数据库连接那些事儿
- 问答
- 2026-01-24 02:43:22
- 2
在VC++里,你很少会为每一种数据库写一套完全不同的连接代码,那样太累,维护起来也是噩梦,大家通常的做法是使用一个通用的数据库访问接口,然后通过改变连接字符串和少量特定语句来切换不同的数据库,最经典、最原始的方法就是使用微软的ODBC。
(来源:微软开发者网络MSDN关于ODBC的概述) ODBC就像是一个翻译官,你的VC++程序只需要学会跟ODBC这个“翻译官”说话(即调用ODBC API),然后告诉这个翻译官你要连接的是Oracle还是SQL Server,ODBC就会去调用对应数据库的驱动程序,把标准的SQL命令“翻译”成Oracle或SQL Server能听懂的方式,这样,你的程序代码主体部分可以基本不变。
具体怎么做呢?大概分几步走:
第一步,准备工作:配数据源,这不是在VC++代码里配,而是在Windows系统里配,你需要为你的Oracle数据库和SQL Server数据库分别创建一个ODBC数据源(DSN)。
- 对于SQL Server,你可以在“ODBC数据源管理器”里,选择“系统DSN”,点击“添加”,然后选择“SQL Server”的驱动程序,接着按照向导一步步输入服务器地址、数据库名、认证方式(Windows认证或SQL Server账号密码)就行了。
- 对于Oracle,同样在“ODBC数据源管理器”里,添加一个数据源,但这次要选择Oracle的驱动程序(比如Oracle in OraClient...),这里你需要输入的主要是数据源名称、TNS服务名(这个需要在Oracle的tnsnames.ora文件里配置好)以及用户名。
(来源:Oracle官方文档关于配置ODBC连接的部分) 配好之后,你的电脑就认识这两个“数据源”了,VC++程序可以直接通过数据源名称来访问。
第二步,写VC++代码,使用ODBC API的经典步骤是这样的:
- 分配环境句柄(SQLAllocHandle)。
- 分配连接句柄(SQLAllocHandle)。
- 用SQLConnect或SQLDriverConnect函数连接数据库,这里就是关键了!连接哪个库,就看你传入的数据源名称(DSN)是什么,连SQL Server就传"Your_SQLServer_DSN",连Oracle就传"Your_Oracle_DSN",账号密码也随之改变。
- 分配语句句柄(SQLAllocHandle)。
- 执行SQL语句(SQLExecDirect),这里有个需要注意的地方:虽然ODBC试图标准化SQL,但Oracle和SQL Server的SQL语法还是有细微差别的,获取当前日期,SQL Server是
GETDATE(),Oracle是SYSDATE,对于这种差异,你可能需要写一些条件编译代码(用#ifdef之类的),或者把不同的SQL语句放在配置文件里,根据连接的数据库类型来读取不同的语句。 - 处理结果集(SQLFetch, SQLGetData等),这部分代码对于两种数据库通常是通用的,因为ODBC帮我们统一了取数据的接口。
- 按顺序释放所有句柄,断开连接。
(来源:MSDN ODBC API参考文档) 举个例子,连接时的代码片段可能长这样:

// 假设已经分配了环境句柄 henv 和连接句柄 hdbc SQLCHAR* dsn_sqlserver = (SQLCHAR*)"MySqlServerDSN"; SQLCHAR* uid = (SQLCHAR*)"sa"; SQLCHAR* pwd = (SQLCHAR*)"password"; RETCODE ret = SQLConnect(hdbc, dsn_sqlserver, SQL_NTS, uid, SQL_NTS, pwd, SQL_NTS); // 或者连接Oracle SQLCHAR* dsn_oracle = (SQLCHAR*)"MyOracleDSN"; SQLCHAR* uid_o = (SQLCHAR*)"scott"; SQLCHAR* pwd_o = (SQLCHAR*)"tiger"; RETCODE ret2 = SQLConnect(hdbc, dsn_oracle, SQL_NTS, uid_o, SQL_NTS, pwd_o, SQL_NTS);
你看,除了连接参数不一样,其他代码结构完全一致。
除了最基础的ODBC API,为了更方便,很多人会选择使用封装得更好的类库,最著名的就是微软的MFC ODBC类,比如CDatabase和CRecordset。
(来源:MFC技术文档)
用CDatabase类,连接数据库就变得更简单了:
CDatabase db;
// 连接SQL Server
BOOL bOk = db.OpenEx(_T("DSN=MySqlServerDSN;UID=sa;PWD=password"));
// 或者连接Oracle
BOOL bOk2 = db.OpenEx(_T("DSN=MyOracleDSN;UID=scott;PWD=tiger"));
然后使用CRecordset类来执行查询和操作数据,MFC把这些API调用封装成了类的成员函数,代码写起来更直观,更符合C++的风格,但底层原理还是ODBC。

世界在发展,除了ODBC,还有其他选择,比如ADO(ActiveX Data Objects)。
(来源:MSDN ADO文档) ADO是通过OLE DB提供者来连接数据库的,它本身也是一套COM组件,在VC++里用ADO稍微麻烦点,因为要处理COM的初始化,但它的功能也很强大,连接字符串是它的核心,搞定Oracle和SQL Server,关键还是在于构造正确的连接字符串。
- 对于SQL Server,连接字符串可能是:"Provider=SQLOLEDB;Data Source=服务器名;Initial Catalog=数据库名;User ID=sa;Password=password;"
- 对于Oracle,可能是:"Provider=OraOLEDB.Oracle;Data Source=Oracle服务名;User ID=scott;Password=tiger;"
在VC++代码里,你只需要动态改变这个连接字符串,然后用ADO的Connection对象打开连接即可,后续使用Recordset对象进行操作。
在VC++里同时搞定Oracle和SQL Server,精髓不在于写两套代码,而在于:
- 选择统一的接口:ODBC是经久耐用的选择,MFC ODBC类让其更易用,ADO是另一个常见选择。
- 隔离变化的部分:将数据库连接字符串(甚至那些有语法差异的SQL语句)作为可配置的变量,可以把它们放在配置文件(如.ini文件)、注册表或者程序的设置对话框里。
- 代码逻辑复用:连接成功后的数据查询、遍历、更新等操作逻辑,尽量写成通用的函数,通过传入不同的连接句柄或对象来工作。
这样,你的程序就能以一种相对优雅的方式,在背后是SQL Server还是Oracle数据库之间灵活切换了,而无需重写大量的底层数据库访问代码,完全避免任何修改是不可能的,特别是当SQL语法存在较大差异时,你需要小心处理这些点。
本文由钊智敏于2026-01-24发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:http://waw.haoid.cn/wenda/84826.html
