获取我的Qt应用程序中可用ODBC数据源的列表

获取我的Qt应用程序中可用ODBC数据源的列表,qt,odbc,Qt,Odbc,在我的Windows框中,我可以列出用户和系统ODBC DSN。例如: QSqlDatabase db = QSqlDatabase::addDatabase("QODBC"); db.setDatabaseName("M10-Server-Production"); 在我的代码中,我可以使用数据源的名称连接到数据库。例如: QSqlDatabase db = QSqlDatabase::addDatabase("QODBC"); db.setDatabaseName("M10-Server

在我的Windows框中,我可以列出用户和系统ODBC DSN。例如:

QSqlDatabase db = QSqlDatabase::addDatabase("QODBC");
db.setDatabaseName("M10-Server-Production");

在我的代码中,我可以使用数据源的名称连接到数据库。例如:

QSqlDatabase db = QSqlDatabase::addDatabase("QODBC");
db.setDatabaseName("M10-Server-Production");
我想获得数据源名称列表,包括用户和系统,过滤它们以仅包括适合我的应用程序的名称,在本例中,它们将以“M10服务器”开始,然后将列表提供给用户,以便用户可以选择连接到哪个数据库

如何以编程方式获取DSN列表


注意:该应用程序可能在Windows或Linux上运行,因此欢迎针对其中一个或两个应用程序的解决方案。

在Windows上,您可以使用函数
SQLDataSources
列出系统上配置的可用系统和/或用户DSN。有关更多信息,请参见此处:

该函数在unixodbc中也可用,但我从未使用过unixodbc

在windows上执行此操作的一些可编译且可用的示例代码:

#include <windows.h>
#include <tchar.h>
#include <iostream>
#include <sql.h>
#include <sqlext.h>
#include <sqlucode.h>

#define BUFF_LENGTH 1024

int _tmain(int argc, _TCHAR* argv[])
{
    // Get an Environment handle
    SQLHENV hEnv = SQL_NULL_HENV;
    // SQLAllocHandle() is for ODBC 3.x
    SQLRETURN ret = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &hEnv);
    // If you do not have ODBC 3.x try with the old version:
    // SQLRETURN ret = SQLAllocEnv(&hEnv);
    if(!SQL_SUCCEEDED(ret))
    {
        std::wcerr << L"No handle" << std::endl;
        return 1;
    }
    // set odbc version (this is required, if not set we get 'function sequence error')
    ret = SQLSetEnvAttr(hEnv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3_80, NULL);
    if(!SQL_SUCCEEDED(ret))
    {
        std::wcerr << L"Failed to set version" << std::endl;
        SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
        return 1;
    }

    // Query sources
    SQLWCHAR nameBuffer[BUFF_LENGTH];
    SQLWCHAR descBuffer[BUFF_LENGTH];
    SQLSMALLINT nameBufferLength = 0;
    SQLSMALLINT descBufferLength = 0;
    ret = SQLDataSources(hEnv, SQL_FETCH_FIRST, nameBuffer, BUFF_LENGTH, &nameBufferLength, descBuffer, BUFF_LENGTH, &descBufferLength);
    if(ret == SQL_NO_DATA)
    {
        // no entries found
        std::wcout << L"No DSN found" << std::endl;
    }
    else if(SQL_SUCCEEDED(ret))
    {
        do
        {
            // do something with the name available in nameBuffer now..
            std::wcerr << L"Name: " << nameBuffer << std::endl;
            // then fetch the next record
            ret = SQLDataSources(hEnv, SQL_FETCH_NEXT, nameBuffer, BUFF_LENGTH, &nameBufferLength, descBuffer, BUFF_LENGTH, &descBufferLength);
        } while(ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO);
    }
    else
    {
        SQLSMALLINT recNr = 1;
        SQLRETURN ret = SQL_SUCCESS;
        while(ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO)
        {
            SQLWCHAR errMsg[SQL_MAX_MESSAGE_LENGTH + 1];
            SQLWCHAR sqlState[5 + 1];
            errMsg[0] = 0;
            SQLINTEGER nativeError;
            SQLSMALLINT cb = 0;
            ret = SQLGetDiagRec(SQL_HANDLE_ENV, hEnv, recNr, sqlState, &nativeError, errMsg, SQL_MAX_MESSAGE_LENGTH + 1, &cb);
            if(ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO)
            {
                std::wcerr << L"ERROR; native: " << nativeError << L"; state: " << sqlState << L"; msg: " << errMsg << std::endl;
            }
            ++recNr;
        }
        std::wcerr << L"Failed";

        SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
        return 1;
    }


    SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
    return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#定义BUFF_长度1024
int _tmain(int argc,_TCHAR*argv[]
{
//获取环境句柄
SQLHENV hEnv=SQL\u NULL\u hEnv;
//SQLAllocHandle()用于ODBC 3.x
SQLRETURN ret=SQLAllocHandle(SQL\u HANDLE\u ENV、SQL\u NULL\u HANDLE和hEnv);
//如果没有ODBC 3.x,请尝试使用旧版本:
//SQLRETURN-ret=SQLAllocEnv(&hEnv);
如果(!SQL_成功(ret))
{

std::wcerr在windows上,您可以使用函数
SQLDataSources
列出系统上配置的可用系统和/或用户DSN。有关更多信息,请参阅此处:

该函数在unixodbc中也可用,但我从未使用过unixodbc

在windows上执行此操作的一些可编译且可用的示例代码:

#include <windows.h>
#include <tchar.h>
#include <iostream>
#include <sql.h>
#include <sqlext.h>
#include <sqlucode.h>

#define BUFF_LENGTH 1024

int _tmain(int argc, _TCHAR* argv[])
{
    // Get an Environment handle
    SQLHENV hEnv = SQL_NULL_HENV;
    // SQLAllocHandle() is for ODBC 3.x
    SQLRETURN ret = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &hEnv);
    // If you do not have ODBC 3.x try with the old version:
    // SQLRETURN ret = SQLAllocEnv(&hEnv);
    if(!SQL_SUCCEEDED(ret))
    {
        std::wcerr << L"No handle" << std::endl;
        return 1;
    }
    // set odbc version (this is required, if not set we get 'function sequence error')
    ret = SQLSetEnvAttr(hEnv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3_80, NULL);
    if(!SQL_SUCCEEDED(ret))
    {
        std::wcerr << L"Failed to set version" << std::endl;
        SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
        return 1;
    }

    // Query sources
    SQLWCHAR nameBuffer[BUFF_LENGTH];
    SQLWCHAR descBuffer[BUFF_LENGTH];
    SQLSMALLINT nameBufferLength = 0;
    SQLSMALLINT descBufferLength = 0;
    ret = SQLDataSources(hEnv, SQL_FETCH_FIRST, nameBuffer, BUFF_LENGTH, &nameBufferLength, descBuffer, BUFF_LENGTH, &descBufferLength);
    if(ret == SQL_NO_DATA)
    {
        // no entries found
        std::wcout << L"No DSN found" << std::endl;
    }
    else if(SQL_SUCCEEDED(ret))
    {
        do
        {
            // do something with the name available in nameBuffer now..
            std::wcerr << L"Name: " << nameBuffer << std::endl;
            // then fetch the next record
            ret = SQLDataSources(hEnv, SQL_FETCH_NEXT, nameBuffer, BUFF_LENGTH, &nameBufferLength, descBuffer, BUFF_LENGTH, &descBufferLength);
        } while(ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO);
    }
    else
    {
        SQLSMALLINT recNr = 1;
        SQLRETURN ret = SQL_SUCCESS;
        while(ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO)
        {
            SQLWCHAR errMsg[SQL_MAX_MESSAGE_LENGTH + 1];
            SQLWCHAR sqlState[5 + 1];
            errMsg[0] = 0;
            SQLINTEGER nativeError;
            SQLSMALLINT cb = 0;
            ret = SQLGetDiagRec(SQL_HANDLE_ENV, hEnv, recNr, sqlState, &nativeError, errMsg, SQL_MAX_MESSAGE_LENGTH + 1, &cb);
            if(ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO)
            {
                std::wcerr << L"ERROR; native: " << nativeError << L"; state: " << sqlState << L"; msg: " << errMsg << std::endl;
            }
            ++recNr;
        }
        std::wcerr << L"Failed";

        SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
        return 1;
    }


    SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
    return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#定义BUFF_长度1024
int _tmain(int argc,_TCHAR*argv[]
{
//获取环境句柄
SQLHENV hEnv=SQL\u NULL\u hEnv;
//SQLAllocHandle()用于ODBC 3.x
SQLRETURN ret=SQLAllocHandle(SQL\u HANDLE\u ENV、SQL\u NULL\u HANDLE和hEnv);
//如果没有ODBC 3.x,请尝试使用旧版本:
//SQLRETURN-ret=SQLAllocEnv(&hEnv);
如果(!SQL_成功(ret))
{

std::wcerr在windows上,您可以使用函数
SQLDataSources
列出系统上配置的可用系统和/或用户DSN。有关更多信息,请参阅此处:

该函数在unixodbc中也可用,但我从未使用过unixodbc

在windows上执行此操作的一些可编译且可用的示例代码:

#include <windows.h>
#include <tchar.h>
#include <iostream>
#include <sql.h>
#include <sqlext.h>
#include <sqlucode.h>

#define BUFF_LENGTH 1024

int _tmain(int argc, _TCHAR* argv[])
{
    // Get an Environment handle
    SQLHENV hEnv = SQL_NULL_HENV;
    // SQLAllocHandle() is for ODBC 3.x
    SQLRETURN ret = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &hEnv);
    // If you do not have ODBC 3.x try with the old version:
    // SQLRETURN ret = SQLAllocEnv(&hEnv);
    if(!SQL_SUCCEEDED(ret))
    {
        std::wcerr << L"No handle" << std::endl;
        return 1;
    }
    // set odbc version (this is required, if not set we get 'function sequence error')
    ret = SQLSetEnvAttr(hEnv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3_80, NULL);
    if(!SQL_SUCCEEDED(ret))
    {
        std::wcerr << L"Failed to set version" << std::endl;
        SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
        return 1;
    }

    // Query sources
    SQLWCHAR nameBuffer[BUFF_LENGTH];
    SQLWCHAR descBuffer[BUFF_LENGTH];
    SQLSMALLINT nameBufferLength = 0;
    SQLSMALLINT descBufferLength = 0;
    ret = SQLDataSources(hEnv, SQL_FETCH_FIRST, nameBuffer, BUFF_LENGTH, &nameBufferLength, descBuffer, BUFF_LENGTH, &descBufferLength);
    if(ret == SQL_NO_DATA)
    {
        // no entries found
        std::wcout << L"No DSN found" << std::endl;
    }
    else if(SQL_SUCCEEDED(ret))
    {
        do
        {
            // do something with the name available in nameBuffer now..
            std::wcerr << L"Name: " << nameBuffer << std::endl;
            // then fetch the next record
            ret = SQLDataSources(hEnv, SQL_FETCH_NEXT, nameBuffer, BUFF_LENGTH, &nameBufferLength, descBuffer, BUFF_LENGTH, &descBufferLength);
        } while(ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO);
    }
    else
    {
        SQLSMALLINT recNr = 1;
        SQLRETURN ret = SQL_SUCCESS;
        while(ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO)
        {
            SQLWCHAR errMsg[SQL_MAX_MESSAGE_LENGTH + 1];
            SQLWCHAR sqlState[5 + 1];
            errMsg[0] = 0;
            SQLINTEGER nativeError;
            SQLSMALLINT cb = 0;
            ret = SQLGetDiagRec(SQL_HANDLE_ENV, hEnv, recNr, sqlState, &nativeError, errMsg, SQL_MAX_MESSAGE_LENGTH + 1, &cb);
            if(ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO)
            {
                std::wcerr << L"ERROR; native: " << nativeError << L"; state: " << sqlState << L"; msg: " << errMsg << std::endl;
            }
            ++recNr;
        }
        std::wcerr << L"Failed";

        SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
        return 1;
    }


    SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
    return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#定义BUFF_长度1024
int _tmain(int argc,_TCHAR*argv[]
{
//获取环境句柄
SQLHENV hEnv=SQL\u NULL\u hEnv;
//SQLAllocHandle()用于ODBC 3.x
SQLRETURN ret=SQLAllocHandle(SQL\u HANDLE\u ENV、SQL\u NULL\u HANDLE和hEnv);
//如果没有ODBC 3.x,请尝试使用旧版本:
//SQLRETURN-ret=SQLAllocEnv(&hEnv);
如果(!SQL_成功(ret))
{

std::wcerr在windows上,您可以使用函数
SQLDataSources
列出系统上配置的可用系统和/或用户DSN。有关更多信息,请参阅此处:

该函数在unixodbc中也可用,但我从未使用过unixodbc

在windows上执行此操作的一些可编译且可用的示例代码:

#include <windows.h>
#include <tchar.h>
#include <iostream>
#include <sql.h>
#include <sqlext.h>
#include <sqlucode.h>

#define BUFF_LENGTH 1024

int _tmain(int argc, _TCHAR* argv[])
{
    // Get an Environment handle
    SQLHENV hEnv = SQL_NULL_HENV;
    // SQLAllocHandle() is for ODBC 3.x
    SQLRETURN ret = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &hEnv);
    // If you do not have ODBC 3.x try with the old version:
    // SQLRETURN ret = SQLAllocEnv(&hEnv);
    if(!SQL_SUCCEEDED(ret))
    {
        std::wcerr << L"No handle" << std::endl;
        return 1;
    }
    // set odbc version (this is required, if not set we get 'function sequence error')
    ret = SQLSetEnvAttr(hEnv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3_80, NULL);
    if(!SQL_SUCCEEDED(ret))
    {
        std::wcerr << L"Failed to set version" << std::endl;
        SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
        return 1;
    }

    // Query sources
    SQLWCHAR nameBuffer[BUFF_LENGTH];
    SQLWCHAR descBuffer[BUFF_LENGTH];
    SQLSMALLINT nameBufferLength = 0;
    SQLSMALLINT descBufferLength = 0;
    ret = SQLDataSources(hEnv, SQL_FETCH_FIRST, nameBuffer, BUFF_LENGTH, &nameBufferLength, descBuffer, BUFF_LENGTH, &descBufferLength);
    if(ret == SQL_NO_DATA)
    {
        // no entries found
        std::wcout << L"No DSN found" << std::endl;
    }
    else if(SQL_SUCCEEDED(ret))
    {
        do
        {
            // do something with the name available in nameBuffer now..
            std::wcerr << L"Name: " << nameBuffer << std::endl;
            // then fetch the next record
            ret = SQLDataSources(hEnv, SQL_FETCH_NEXT, nameBuffer, BUFF_LENGTH, &nameBufferLength, descBuffer, BUFF_LENGTH, &descBufferLength);
        } while(ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO);
    }
    else
    {
        SQLSMALLINT recNr = 1;
        SQLRETURN ret = SQL_SUCCESS;
        while(ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO)
        {
            SQLWCHAR errMsg[SQL_MAX_MESSAGE_LENGTH + 1];
            SQLWCHAR sqlState[5 + 1];
            errMsg[0] = 0;
            SQLINTEGER nativeError;
            SQLSMALLINT cb = 0;
            ret = SQLGetDiagRec(SQL_HANDLE_ENV, hEnv, recNr, sqlState, &nativeError, errMsg, SQL_MAX_MESSAGE_LENGTH + 1, &cb);
            if(ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO)
            {
                std::wcerr << L"ERROR; native: " << nativeError << L"; state: " << sqlState << L"; msg: " << errMsg << std::endl;
            }
            ++recNr;
        }
        std::wcerr << L"Failed";

        SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
        return 1;
    }


    SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
    return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#定义BUFF_长度1024
int _tmain(int argc,_TCHAR*argv[]
{
//获取环境句柄
SQLHENV hEnv=SQL\u NULL\u hEnv;
//SQLAllocHandle()用于ODBC 3.x
SQLRETURN ret=SQLAllocHandle(SQL\u HANDLE\u ENV、SQL\u NULL\u HANDLE和hEnv);
//如果没有ODBC 3.x,请尝试使用旧版本:
//SQLRETURN-ret=SQLAllocEnv(&hEnv);
如果(!SQL_成功(ret))
{

std::wcerr?-这是一个应用程序支持的驱动程序列表。@SaZ yes-在我的windows框中,它返回以下列表:QSQLITE、QMYSQL、QMYSQL3、QODBC、QODBC3、QPSQL、QPSQL7。在我的Linux框中,它返回类似的内容。也就是说,它不返回数据源,只返回已安装的驱动程序。不过,谢谢你的建议?-这是一个应用程序支持的驱动程序列表。@SaZ yes-在我的windows框中,它返回以下列表:QSQLITE、QMYSQL、QMYSQL3、QODBC、QODBC3、QPSQL、QPSQL7。在我的Linux框中,它返回类似的内容。也就是说,它不返回数据源,只返回已安装的驱动程序。不过,谢谢你的建议。?-这是一个列表您的应用程序支持的驱动程序列表。@SaZ yes-在我的windows框中,它返回以下列表:QSQLITE、QMYSQL、QMYSQL3、QODBC、QODBC3、QPSQL、QPSQL7。在我的Linux框中,它返回类似的内容。也就是说,它不返回数据源,只返回已安装的驱动程序。不过,感谢您的建议。?-这是一个驱动程序列表,su由您的应用程序支持。@SaZ yes-在我的windows框中,它返回以下列表:QSQLITE、QMYSQL、QMYSQL3、QODBC、QODBC3、QPSQL、QPSQL7。在我的Linux框中,它返回类似的内容。也就是说,它不返回数据源,只返回安装的驱动程序。不过,感谢您的建议。谢谢您的回答。这正是这是我一直在寻找的东西。不过,我在通过编译器获取SQLAllocHandle()时遇到了问题。我得到了一个“未解析的外部符号”报告错误。您知道如何排序吗?再次感谢。@Michael:在Windows上?我使用visual studio 2013测试了上述代码,您应该能够创建一个新的win32控制台应用程序,并将上述内容复制到main.cpp中(替换所有其他内容)。您有所有包含项吗?如果ODBCVER>=0x0300,则应在sql.h中声明SQLAllocHandle。谢谢。我使用的是Qt Creator而不是VS。我复制了包含项列表,编译器对其中任何一项都没有异议。我需要检查ODBC版本。我怀疑QTCreator正在拾取一个ve