调用存储过程时未检索到任何数据

No data retrieved while calling a stored procedure

本文关键字:任何 数据 检索 存储过程 调用      更新时间:2023-10-16

我正在尝试从VC++调用存储过程。

下面是存储过程的外观:

public static void SqlStoredProcedure2(string name, out byte[] backup)
{
    using (SqlConnection conn = new SqlConnection("context connection=true"))
    {
        SqlCommand cmd = new SqlCommand();
        cmd.Connection = conn;
        conn.Open();
        cmd.CommandText = "SELECT EmployeePhoto FROM [dbo].[DimEmployee] where FirstName like '%@name%'";
        SqlDataReader reader = null;
        reader = cmd.ExecuteReader();
        backup = null;
        while (reader.Read())
        {
            backup = (byte[])reader["EmployeePhoto"];
        }
        conn.Close();
    }
}

c++ 代码如下所示:

RETCODE retcode = SQLAllocHandle(SQL_HANDLE_STMT,hdbc,&hstmt);
retcode = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, 5, 0, "Alan", 0, &cbParm1);
unsigned char ptr[8000] = "";
cbParm2 = 8000;
retcode = SQLBindParameter(hstmt, 2, SQL_PARAM_OUTPUT, SQL_C_BINARY, SQL_VARBINARY, 0, 0, ptr, 0, &cbParm2);
retcode = SQLExecDirectA(hstmt, (UCHAR*)"{call SqlStoredProcedure2(?, ?)}", SQL_NTS);

当我检查返回的代码时没有错误,但没有任何ptr?这是怎么回事?

我建议您在集成之前对 C# 代码进行单元测试。 C# 代码存在很多问题。 第一个是没有在 C# 代码中传递参数。

在执行读取器之前添加以下内容。

cmd.Parameters.AddWithValue( "@name", name );

此外,您的 while 循环毫无意义(您忽略了除最后一张图片之外的所有图片),您应该对 cmd 使用 using

作为旁注请注意 - 像这样在开头和结尾带有通配符的搜索将非常非常慢。

SQL Server 将全文搜索作为一项单独的功能提供。

好的,我解决了这个问题,这是正确的调用方法。

    SQLRETURN retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
    if ( (retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO) )
    {
        printf("SQLAllocHandle(hstmt1) Failednn");
        return;
    }
    retcode = SQLPrepareA(hstmt,(SQLCHAR*)"{call StoreProcedure2(?)}",SQL_NTS);
    SQLSMALLINT NumParams1, DataType1, DecimalDigits1, Nullable1;
    SQLULEN ParamSize1;
    unsigned char input1[50000] = "";
    SQLLEN inputlen1 = sizeof(input1);
    SQLINTEGER cbValue1 = sizeof(input1);//actual size of data in or out
    retcode = SQLDescribeParam(hstmt, 1, &DataType1, &ParamSize1, &DecimalDigits1, &Nullable1);
    retcode = SQLBindParameter(hstmt, 1, SQL_PARAM_OUTPUT, SQL_C_BINARY, DataType1, ParamSize1, DecimalDigits1, &input1, inputlen1 ,&cbValue1);
    retcode = SQLExecDirectA(hstmt, (UCHAR*)"{call StoreProcedure2(?)}", SQL_NTS);
    if ( (retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO) ) 
    {
        printf("SQLExecDirect Failednn");
        extract_error(hstmt,SQL_HANDLE_STMT);
        return;
    }
}
"

8000 对我来说似乎是一个死赠品。 对不起,为什么我把 8000 放在那里,因为这就是生成的查询的样子,

CREATE PROCEDURE [dbo].[SqlStoredProcedure2] @name [nvarchar](4000),
@backup [varbinary](8000)    OUTPUT
AS EXTERNAL NAME [Database1].[StoredProcedures].[SqlStoredProcedure2];

我认为一旦我改变尺寸,它就会发生变化,但这并没有发生。

现在我正在尝试更改缓冲区的大小。

好的,

我解决了大小问题,我需要使用

SqlFacet(MaxSize = -1)

参数,因此 SQL 存储过程如下所示

C#

[Microsoft.SqlServer.Server.SqlProcedure]
public static void SqlStoredProcedure2(string name, 
[SqlFacet(MaxSize = -1)]out byte[] backup)

和生成的查询

CREATE PROCEDURE [dbo].[SqlStoredProcedure2] @name [nvarchar](4000),
@backup [varbinary](MAX)     OUTPUT
AS EXTERNAL NAME [Database1].[StoredProcedures].[SqlStoredProcedure2];

我仍然运气不好,在 C++ 中输出 PTR 中没有任何内容。