OLEDB:在不选择任何行的情况下获取 SQL Server CE 表的列元数据的最快方法是什么?

发布于 2024-12-27 02:56:50 字数 205 浏览 5 评论 0原文

我必须将 OLE DB 与 SQL Server CE 一起使用。我的任务是获取表中所有列的元数据。

一种方法是选择任意行的所有字段,然后从结果行集中获取 IColumnInfo。然而,这是以选择行为代价来完成的。

我的问题 - 这是最快的方法还是有更好的方法来获取表中所有列的 DBCOLUMNINFO 对象?

I have to use OLE DB with an SQL Server CE. My task is to obtain the metadata on all the columns in a table.

One way to do it is select all the fields of any row and then obtain IColumnInfo from the resulting row set. However, this is done at the cost of selecting a row.

My question - is it the fastest way or is there a better way to get hold on the DBCOLUMNINFO objects for all the columns in a table?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

泪冰清 2025-01-03 02:56:50

您可以在 INFORMATION_SCHEMA 上使用 SELECT 语句来提取特定表的列信息:

SELECT *
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = ?

但是,在 OLEDB 中,有一个 IDBSchemaRowset,它可以快得多。我整理了一个小型 C++ 代码示例,该示例显示了打开 OLEDB 连接 (OpenDatabase) 并使用 IRowset (GetSchemaColumns) 提取列信息。您需要添加处理 IRowset 返回的结果(运行):

#include <windows.h>
#include <atlbase.h>
#include <oleauto.h>
#include <oledb.h>

HRESULT OpenDatabase(LPOLESTR szPath, IDBInitialize **ppIDBInitialize)
{
    HRESULT hr = S_OK;
    CComPtr<IDBInitialize> spIDBInitialize;
    hr = spIDBInitialize.CoCreateInstance(OLESTR("Microsoft.SQLLITE.MOBILE.OLEDB.3.0"));
    CComPtr<IDBProperties> spIDBProperties;
    spIDBProperties = spIDBInitialize;
    CComVariant vDataSource(szPath);
    DBPROP dbProp = { DBPROP_INIT_DATASOURCE, DBPROPOPTIONS_REQUIRED, 0, DB_NULLID, vDataSource };
    DBPROPSET dbPropSet = { &dbProp, 1, DBPROPSET_DBINIT };
    hr = spIDBProperties->SetProperties(1, &dbPropSet);
    hr = spIDBInitialize->Initialize();
    *ppIDBInitialize = spIDBInitialize.Detach();
    return hr;
}

HRESULT GetSchemaColumns(IUnknown *pDataSource, LPOLESTR pTableName, IRowset **ppIRowset)
{
    HRESULT hr = S_OK;
    CComPtr<IDBCreateSession> spIDBCreateSession;
    hr = pDataSource->QueryInterface(IID_IDBCreateSession, (void**) &spIDBCreateSession);
    CComPtr<IDBCreateCommand> spIDBCreateCommand;
    hr = spIDBCreateSession->CreateSession(NULL, IID_IDBCreateCommand, (IUnknown**) &spIDBCreateCommand);
    CComPtr<IDBSchemaRowset> spIDBSchemaRowset;
    hr = spIDBCreateCommand->QueryInterface(IID_IDBSchemaRowset, (void**) &spIDBSchemaRowset);
    CComVariant vRestrictions[CRESTRICTIONS_DBSCHEMA_COLUMNS];
    vRestrictions[2] = pTableName;
    CComPtr<IRowset> spIRowset;
    hr = spIDBSchemaRowset->GetRowset(NULL, DBSCHEMA_COLUMNS, CRESTRICTIONS_DBSCHEMA_COLUMNS, vRestrictions, IID_IRowset, NULL, NULL, (IUnknown**) &spIRowset);
    *ppIRowset = spIRowset.Detach();
    return hr;
}

HRESULT Run()
{
    HRESULT hr = S_OK;
    CComPtr<IDBInitialize> spIDBInitialize;
    hr = OpenDatabase(OLESTR("MyDatabase.sdf"), &spIDBInitialize);
    CComPtr<IRowset> spIRowset;
    hr = GetSchemaColumns(spIDBInitialize, OLESTR("MyTableName"), &spIRowset);
    DBCOUNTITEM cRows = 0;
    HROW hRow = NULL;
    HROW *phRow = &hRow;
    hr = spIRowset->GetNextRows(DB_NULL_HCHAPTER, 0, 1, &cRows, &phRow);
    while (SUCCEEDED(hr) && cRows > 0)
    {
        // Do handling of a row fetched from INFORMATION_SCHEMA.COLUMN here
        // ...
        hr = spIRowset->ReleaseRows(1, phRow, NULL, NULL, NULL);
        hr = spIRowset->GetNextRows(DB_NULL_HCHAPTER, 0, 1, &cRows, &phRow);
    }
    return hr;
}

You can use a SELECT statement on the INFORMATION_SCHEMA to extract COLUMN information for a particular table:

SELECT *
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = ?

However, in OLEDB there's an IDBSchemaRowset which can be a lot faster. I've put together a small C++ code sample that shows opening an OLEDB connection (OpenDatabase) and extracting column information using IRowset (GetSchemaColumns). You need to add processing the results from IRowset returned (Run):

#include <windows.h>
#include <atlbase.h>
#include <oleauto.h>
#include <oledb.h>

HRESULT OpenDatabase(LPOLESTR szPath, IDBInitialize **ppIDBInitialize)
{
    HRESULT hr = S_OK;
    CComPtr<IDBInitialize> spIDBInitialize;
    hr = spIDBInitialize.CoCreateInstance(OLESTR("Microsoft.SQLLITE.MOBILE.OLEDB.3.0"));
    CComPtr<IDBProperties> spIDBProperties;
    spIDBProperties = spIDBInitialize;
    CComVariant vDataSource(szPath);
    DBPROP dbProp = { DBPROP_INIT_DATASOURCE, DBPROPOPTIONS_REQUIRED, 0, DB_NULLID, vDataSource };
    DBPROPSET dbPropSet = { &dbProp, 1, DBPROPSET_DBINIT };
    hr = spIDBProperties->SetProperties(1, &dbPropSet);
    hr = spIDBInitialize->Initialize();
    *ppIDBInitialize = spIDBInitialize.Detach();
    return hr;
}

HRESULT GetSchemaColumns(IUnknown *pDataSource, LPOLESTR pTableName, IRowset **ppIRowset)
{
    HRESULT hr = S_OK;
    CComPtr<IDBCreateSession> spIDBCreateSession;
    hr = pDataSource->QueryInterface(IID_IDBCreateSession, (void**) &spIDBCreateSession);
    CComPtr<IDBCreateCommand> spIDBCreateCommand;
    hr = spIDBCreateSession->CreateSession(NULL, IID_IDBCreateCommand, (IUnknown**) &spIDBCreateCommand);
    CComPtr<IDBSchemaRowset> spIDBSchemaRowset;
    hr = spIDBCreateCommand->QueryInterface(IID_IDBSchemaRowset, (void**) &spIDBSchemaRowset);
    CComVariant vRestrictions[CRESTRICTIONS_DBSCHEMA_COLUMNS];
    vRestrictions[2] = pTableName;
    CComPtr<IRowset> spIRowset;
    hr = spIDBSchemaRowset->GetRowset(NULL, DBSCHEMA_COLUMNS, CRESTRICTIONS_DBSCHEMA_COLUMNS, vRestrictions, IID_IRowset, NULL, NULL, (IUnknown**) &spIRowset);
    *ppIRowset = spIRowset.Detach();
    return hr;
}

HRESULT Run()
{
    HRESULT hr = S_OK;
    CComPtr<IDBInitialize> spIDBInitialize;
    hr = OpenDatabase(OLESTR("MyDatabase.sdf"), &spIDBInitialize);
    CComPtr<IRowset> spIRowset;
    hr = GetSchemaColumns(spIDBInitialize, OLESTR("MyTableName"), &spIRowset);
    DBCOUNTITEM cRows = 0;
    HROW hRow = NULL;
    HROW *phRow = &hRow;
    hr = spIRowset->GetNextRows(DB_NULL_HCHAPTER, 0, 1, &cRows, &phRow);
    while (SUCCEEDED(hr) && cRows > 0)
    {
        // Do handling of a row fetched from INFORMATION_SCHEMA.COLUMN here
        // ...
        hr = spIRowset->ReleaseRows(1, phRow, NULL, NULL, NULL);
        hr = spIRowset->GetNextRows(DB_NULL_HCHAPTER, 0, 1, &cRows, &phRow);
    }
    return hr;
}
过度放纵 2025-01-03 02:56:50

如果您想避免选择行,请使用 where 1 = 0 作为 where 子句。

您还可以使用 INFORMATION_SCHEMA 表。

Microsoft 文档:信息架构 (SQL Server Compact)

If you want to avoid selecting rows, use where 1 = 0 as your where clause.

You could also use the INFORMATION_SCHEMA tables.

Microsoft docs: Information Schema (SQL Server Compact)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文