如何在C++中使用OLEDB连接到MDF数据库文件
How to attach to an MDF database file using OLEDB in C++?
我的C++代码成功地恢复了SQL Server数据库备份文件,然后使用OLEDB API从生成的数据库中提取必要的信息。
这是我的C++代码,在代码的最后,我得到了一个IDBCreateCommand
实例,可以用于对恢复的数据库执行各种查询:
DB::DB(LPCWSTR wszDataSource, LPCWSTR wszBackupFilePath, LPCWSTR wszRestoreFolderPath)
{
fs::path backupFilePath = fs::canonical(wszBackupFilePath).make_preferred();
fs::path restoreFolderPath = fs::canonical(wszRestoreFolderPath).make_preferred();
std::wstring db = backupFilePath.leaf().stem().wstring();
boost::wformat restoreQueryFmt(L"RESTORE DATABASE [%2%] FROM DISK = N'%1%' WITH REPLACE, STATS = 10, MOVE N'%2%' TO N'%3%\%2%.mdf', MOVE N'%2%_log' TO N'%3%\%2%.LDF'");
std::wstring query = (restoreQueryFmt % backupFilePath.wstring() % db % restoreFolderPath.wstring()).str();
IDBInitializePtr spDBInitialize;
HRESULT hr = spDBInitialize.CreateInstance(CLSID_SQLNCLI10, NULL);
if (REGDB_E_CLASSNOTREG == hr)
{
hr = spDBInitialize.CreateInstance(CLSID_SQLNCLI, NULL);
}
_HRESULT_CHECK3(spDBInitialize, hr);
_variant_t vDataSource(wszDataSource);
_variant_t vAuth(L"SSPI");
DBPROP dbprop[2]; // property used in property set to initialize provider
dbprop[0].dwPropertyID = DBPROP_INIT_DATASOURCE;
dbprop[0].dwOptions = DBPROPOPTIONS_REQUIRED;
dbprop[0].vValue = vDataSource;
dbprop[1].dwPropertyID = DBPROP_AUTH_INTEGRATED;
dbprop[1].dwOptions = DBPROPOPTIONS_REQUIRED;
dbprop[1].vValue = vAuth;
DBPROPSET dbpropset[1]; // Property Set used to initialize provider
dbpropset[0].guidPropertySet = DBPROPSET_DBINIT;
dbpropset[0].rgProperties = dbprop;
dbpropset[0].cProperties = sizeof(dbprop)/sizeof(dbprop[0]);
// Set initialization properties.
IDBPropertiesPtr spDBProperties = spDBInitialize;
_HRESULT_CHECK(spDBProperties, SetProperties(1, dbpropset));
_HRESULT_CHECK(spDBInitialize, Initialize());
IDBCreateSessionPtr spCreateSession = spDBInitialize;
_HRESULT_CHECK(spCreateSession, CreateSession(NULL, IID_IDBCreateCommand, reinterpret_cast<IUnknown **>(&m_spDBCreateCommand)));
ICommandTextPtr spCommandText;
_HRESULT_CHECK(m_spDBCreateCommand, CreateCommand(NULL, IID_ICommandText, reinterpret_cast<IUnknown **>(&spCommandText)));
_HRESULT_CHECK(spCommandText, SetCommandText(DBGUID_SQL, query.c_str()));
_HRESULT_CHECK(spCommandText, Execute(NULL, IID_NULL, NULL, NULL, NULL));
_HRESULT_CHECK(spCommandText, SetCommandText(DBGUID_SQL, (boost::wformat(L"USE "%1%"") % db).str().c_str()));
_HRESULT_CHECK(spCommandText, Execute(NULL, IID_NULL, NULL, NULL, NULL));
}
它的作用是:
- 使用给定的数据源(如".\SQLEXPRESS")和SSPI集成身份验证方案初始化新的数据库连接
- 执行
RESTORE DATABASE
T-SQL语句,如下所示:RESTORE DATABASE [my_db] FROM DISK = N'c:tempmy_db.ebf' WITH REPLACE, STATS = 10, MOVE 'my_db' TO N'c:tempmy_db.mdf', MOVE N'my_db_log' TO N'c:tempmy_db.LDF'
- 通过运行
USE "my_db"
将新数据库用于后续查询
所以,我恢复数据库备份文件并从那里继续操作没有问题。
现在我面临另一个问题。假设没有备份文件,而是一个已经存在的MDF文件-我如何使用OLEDB C++API连接到它?
谢谢。
编辑
假设.mdf文件附带了数据库引擎所需的所有文件——.ldf和其他需要的文件。
如果只有MDF文件,则无法附加数据库,因为这最多只能是数据库的一半。您需要MD和LDF。以及组成原始数据库的任何附加NDF或辅助LDF文件。
假设MDF和LDF分别为%1%和%3%,那么您所要做的就是执行以下语句:
CREATE DATABASE [%2%]
ON (FILENAME=N'%1%')
, (FILENAME=N'%3')
FOR ATTACH;
请参阅如何使用分离和附加(Transact-SQL)移动数据库
单独连接和MDF的选项确实存在(使用FOR ATTACH_REBUILD_LOG
),但它附带了许多警告,因为它只适用于干净关闭的数据库(否则可能导致数据库损坏)。如果缺少辅助NDF文件,则无法附加数据库。
相关文章:
- 当套接字连接断开时检测C/C++Unix
- 无法在windows上使用mingw将sqlite3与c连接
- 到连接组件算法的问题(递归)
- QTcpSocket在不阻塞GUI的情况下重新连接到服务器
- 无法在C++中建立与MySQL数据库的连接
- PC中的程序和PHONE中的本机描述应用程序之间的数据连接
- 在Qt Creator中,如何在连接到正在运行的进程后查看控制台输出
- 连接 dockerized 模型和 dockerized 数据库时出现"无法 SQLConnect"错误
- 使用 bfs 解决连接组件问题时得到错误的答案
- 在C++的两个字符串中连接以逗号分隔的唯一值
- 如何修复valgrind启动时的致命错误(与libc6-dbg和libc6-dbg:i386连接)
- C++应用程序 MySQL odbc 数据库连接错误:在引发"otl_tmpl_exception<>"实例后终止调用
- OSX蓝牙打开RFCOMMChannelAsync声称已连接,但未建立连接,并且从未调用过委托
- 在 libcurl 连接池中预创建连接
- 套接字连接"Operation not permitted"错误,甚至使用升压/平发器根.cpp
- libcurl 和 DNS ttl 中的内部连接管理
- 如何应用 libcurl 的持久连接选项
- 提升 ASIO - io_service 不要等待连接到线程
- WinSock2:connect() 提供"连接被拒绝"
- 升压信号2将插槽传递到成员功能以断开连接