gpt4 book ai didi

sql-server - 无法使用SQL Server ODBC驱动程序执行同义词存储过程;与OLEDB一起使用

转载 作者:行者123 更新时间:2023-12-02 03:18:12 24 4
gpt4 key购买 nike

此问题是Microsoft ODBC中一系列错误的一部分
司机:


  • ODBC driver fails to raise errors; but instead suppresses them
  • Reading columns out of order returns incorrect results
  • Cannot execute a stored procedure that is a SYNONYM


  • 微软表示他们不会在ODBC中修复这些错误
    司机。


    我有(许多)实际上是同义词的存储过程。该存储过程在一个数据库中规范存在,但在其他数据库中可见。

    该存储过程可以在SQL Server Management Studio中正常执行:
    EXECUTE Report_ThirdParty @ContosoGUID = '{CC0ECA32-BEFA-11E5-8E2A-C86000D0B92A}'

    而且,如果我使用任何OLEDB提供程序连接到SQL Server:
  • SQL Server本机客户端10.0 OLE DB提供程序:Provider=SQLNCLI10;Data Source=contoso.stackoverflow.com;User ID=ContosoManager;Password=correct horse battery staple;
  • 用于SQL Server的Microsoft OLE DB提供程序:Provider=SQLOLEDB;Data Source=contoso.stackoverflow.com;User ID=contoso.stackoverflow.com;Password=correct horse battery staple;

  • 然后,存储过程将正常执行。我得到结果。大家都很高兴。

    但不适用于ODBC驱动程序

    使用 the announcement of the deprecation of OleDb drivers,我想测试使用SQL Server的ODBC驱动程序。当我更改连接以使用其中一种SQL Server ODBC驱动程序(例如“{SQL Server}”)并执行相同的SQL语句时
    EXECUTE Report_ThirdParty @ContosoGUID = '{CC0ECA32-BEFA-11E5-8E2A-C86000D0B92A}'

    我得到错误:

    过程“Report_ThirdParty”的请求失败,因为“Report_ThirdParty”是同义词对象

    无论我将原始的ODBC驱动程序用于SQL Server还是本机客户端,都是如此:
  • SQL Server :Provider=MSDASQL;Driver={SQL Server};Server={contoso.stackoverflow.com};UID={contosoManager};PWD={correct horse battery staple};
  • SQL Server本机客户端11.0 :Provider=MSDASQL;Driver={SQL Server Native Client 11.0};Server={contoso.stackoverflow.com};UID={ContosoManager};PWD={correct horse battery staple};

  • 在这两种变体中,我得到相同的错误:

    [Microsoft] [SQL Server Native Client 11.0] [SQL Server]对过程'Report_ThirdParty'的请求失败,因为'Report_ThirdParty'是同义词对象

    或对于较旧的ODBC驱动程序:

    [Microsoft] [ODBC SQL Server驱动程序] [SQL Server]对过程'Report_ThirdParty'的请求失败,因为'Report_ThirdParty'是同义词对象

    换一种说法:

    过程'%s'的请求失败,因为'%s'是同义词对象

    Errors Connection集合提供了更多信息:
  • 错误#1
  • 编号: 0x80040E14
  • 来源:用于ODBC驱动程序的Microsoft OLE DB提供程序
  • 说明: [Microsoft] [ODBC SQL Server驱动程序] [SQL Server]对过程'Report_ThirdParty'的请求失败,因为'Report_ThirdParty'是同义词对象。
  • SQL状态: 37000
  • NativeError :2809
  • 错误#2
  • 编号: 0x80040E14
  • 来源:用于ODBC驱动程序的Microsoft OLE DB提供程序
  • 说明: [Microsoft] [ODBC SQL Server驱动程序] [SQL Server]未声明游标。
  • SQL状态: 37000
  • NativeError: 16945

  • 放弃切换到ODBC并没有什么害处。而且我不会停止使用同义词。

    但是怎么了,我该如何告诉ODBC驱动程序让SQL Server正常工作?

    SQL事件探查器结果
  • RPC:开始:声明@ p1整数集@ p1 = 0声明@ p3整数集@ p3 = 16388声明@ p4整数集@ p4 = 8193声明@ p5整数集@ p5 = 0 exec sp_cursoropen @ p1输出,N 'EXECUTE Report_ThirdParty @ContosoGUID =''{3492C4E6-D500-4A23-9CAB-CB6582C27ABD}''',@ p3输出,@ p4输出,@ p5输出选择@ p1,@ p3,@ p4,@ p5
  • 异​​常:错误:2809,严重性:18,状态:1
  • 用户错误消息:由于“Report_ThirdParty”是同义词对象,因此对过程“Report_ThirdParty”的请求失败。
  • 异​​常:错误:16945,严重性:16,状态:2
  • 用户错误消息:未声明光标。
  • RPC:已完成::声明@ p1 int集@ p1 = 0声明@ p3 int集@ p3 = 16388声明@ p4 int集@ p4 = 8193声明@ p5 int集@ p5 = 0 exec sp_cursoropen @ p1输出, N'EXECUTE Report_ThirdParty @ContosoGUID =``{3492C4E6-D500-4A23-9CAB-CB6582C27ABD}''',@ p3输出,@ p4输出,@ p5输出选择@ p1,@ p3,@ p4,@ p5

  • 注释
  • 本机(即非.NET)代码。您可以假装它是C,C++,汇编或Delphi。
  • Microsoft SQL Server 2008 R2(SP2)-10.50.4000.0(X64)

  • ODBC的其他意外功能(在OLEDB中起作用)
  • Stackoverflow:Reading columns out of order returns incorrect results
  • Stackoverflow:Cannot execute a stored procedure that is a SYNONYM
  • Stackoverflow:ODBC driver suppresses errors

  • 奖励阅读
  • KB928372: FIX: Error message when you use a synonym for a stored procedure in SQL Server 2005: "A severe error occurred on the current command"
  • 最佳答案

    作为我的评论的后续,这是我的示例(有点不太简单),可在此处使用:

    一个非常简单的存储过程:

    USE [Test]
    GO
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    ALTER procedure [dbo].[foo]
    @p1 int
    AS
    RETURN 13 + @p1

    并且已经创建了该过程的同义词(使用gui工具),名为 dbo.fooSyn

    我可以在SQL Server 2014 Management Studio中执行这两个操作:
    execute foo @p1 = 2
    GO
    execute fooSyn @p1 = 3
    GO

    两条语句均完整无误。

    这是我的测试代码,使用该名称执行一次,并使用同义词执行一次:
    #include <windows.h>
    #include <tchar.h>
    #include <iostream>
    #include <sql.h>
    #include <sqlext.h>
    #include <sqlucode.h>

    void printErrDbc(SQLHDBC hDbc)
    {
    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_DBC, hDbc, 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;
    }
    }

    void printErrStmt(SQLHSTMT hStmt)
    {
    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_STMT, hStmt, 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;
    }
    }

    int _tmain(int argc, _TCHAR* argv[])
    {
    SQLRETURN nResult = 0;
    SQLHANDLE handleEnv = 0;

    nResult = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, (SQLHANDLE*)&handleEnv);

    nResult = SQLSetEnvAttr(handleEnv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3_80, SQL_IS_INTEGER);

    SQLHANDLE handleDBC = 0;
    nResult = SQLAllocHandle(SQL_HANDLE_DBC, handleEnv, (SQLHANDLE*)&handleDBC);

    SQLWCHAR strConnect[256] = L"Driver={SQL Server Native Client 11.0};Server=.\\INSTANCE;Database=Test;Trusted_Connection=yes;";
    SQLWCHAR strConnectOut[1024] = { 0 };
    SQLSMALLINT nNumOut = 0;
    nResult = SQLDriverConnect(handleDBC, NULL, (SQLWCHAR*)strConnect, SQL_NTS, (SQLWCHAR*)strConnectOut, sizeof(strConnectOut),
    &nNumOut, SQL_DRIVER_NOPROMPT);
    if (!SQL_SUCCEEDED(nResult))
    {
    printErrDbc(handleDBC);
    }

    nResult = SQLSetConnectAttr(handleDBC, SQL_ATTR_AUTOCOMMIT, (SQLUINTEGER)SQL_AUTOCOMMIT_OFF, NULL);
    if (!SQL_SUCCEEDED(nResult))
    {
    printErrDbc(handleDBC);
    }

    SQLHSTMT handleStatement = 0;
    nResult = SQLAllocHandle(SQL_HANDLE_STMT, handleDBC, (SQLHANDLE*)&handleStatement);
    if (!SQL_SUCCEEDED(nResult))
    {
    printErrDbc(handleDBC);
    }

    // Bind return code
    SQLINTEGER res = 0;
    SQLLEN cb = 0;
    SWORD sParm1 = 0;
    SQLLEN cbParm1 = SQL_NTS;

    nResult = SQLBindParameter(handleStatement, 1, SQL_PARAM_OUTPUT, SQL_C_SSHORT, SQL_INTEGER, 0, 0, &sParm1, 0, &cbParm1);
    if (!SQL_SUCCEEDED(nResult))
    {
    printErrStmt(handleStatement);
    }

    // And call using synonym name
    nResult = SQLExecDirect(handleStatement, L"{? = call fooSyn(3)}", SQL_NTS);
    if (!SQL_SUCCEEDED(nResult))
    {
    printErrStmt(handleStatement);
    }

    nResult = SQLFetch(handleStatement);
    std::wcout << L"Result is: " << sParm1 << std::endl;

    // Note: It also works using EXECUTE - but I dont remember how to read return value like that.
    nResult = SQLExecDirect(handleStatement, L"execute foo @p1 = 2", SQL_NTS);
    if (!SQL_SUCCEEDED(nResult))
    {
    printErrStmt(handleStatement);
    }
    else
    {
    std::wcout << L"Working using name" << std::endl;
    }
    nResult = SQLExecDirect(handleStatement, L"execute fooSyn @p1 = 2", SQL_NTS);
    if (!SQL_SUCCEEDED(nResult))
    {
    printErrStmt(handleStatement);
    }
    else
    {
    std::wcout << L"Working using synonym" << std::endl;
    }

    return 0;
    }

    打印出预期的输出:
    Result is: 16
    Working using name
    Working using synonym

    那么,您的设置有什么区别?

    总结一下我的设置:
  • SQL Server 2014 Express Edition
  • SQL Server本机客户端11.0版本2011.110.3000.00(但它也仅使用{SQL Server}作为驱动程序也可以工作)
  • Windows 7教授
  • 与Visual Studio 2013一起编译。
  • 使用odbc版本3.8的
  • 同义词和存储过程位于同一数据库中,即使在此数据库中处于相同架构中也是如此。
  • 关于sql-server - 无法使用SQL Server ODBC驱动程序执行同义词存储过程;与OLEDB一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35296182/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com