带有SQL_VARBINARY(MAX)的SQLBindParameter给出“无效的精度值”

时间:2013-02-13 18:20:53

标签: sql-server

使用C ++代码,我试图使用存储过程将大型二进制blob插入到MS SQL服务器中。我要插入的表有5列,类型:

int
varchar
datetime
varbinary(max)
datetime

存储过程需要4个参数:

PROCEDURE [dbo].[spr_fff] 
     @act           AS INT
    ,@id            AS VARCHAR(255)
    ,@timestamp     AS DATETIME
    ,@blob          AS VARBINARY(MAX)

我设置了我的声明(检查了我没有显示的返回值):

const std::string queryString("{Call [spr_fff](?,?,?,?)}");
SQLHSTMT handle = NULL;
SQLAllocHandle(SQL_HANDLE_STMT, m_hConn, &handle);
SQLPrepare(handle, (SQLCHAR *)queryString.c_str(), SQL_NTS);

我绑定前三个参数没有问题,但我似乎无法弄清楚如何绑定第四个参数。代码基本上是:

std::string sData; getData(sData);  //fills sData with the binary data
SQLLEN len1 = ???;
SQLBindParameter( handle, (SQLUSMALLINT)4, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_VARBINARY, len1, 0, (SQLCHAR*)&sData.c_str(), (SQLLEN)sData.size(), NULL);

并且诀窍似乎在弄清楚len1应该是什么。如果sData.size() < 8000,那么len1 = sData.size()工作正常。但如果sData.size() > 8000,似乎没有任何效果。如果我设置len1 = sData.size()len1 = 2147483647,则对SQLBindParameter的调用会导致错误代码&#34;无效的精度值&#34;。如果我将len1 = 0设置为某些(可怕的)文档似乎建议,对SQLBindParameter的调用有效(对于2008本机驱动程序),但执行该语句会产生一个大小为2的blob,即两个默认的0字节,所有输入blob数据都截断为0字节。我已经尝试了所有这些组合与下面列出的所有客户端驱动程序,都无济于事。我做错了什么?????

环境
   客户端操作系统:Windows XP sp3

SQL Server是
         Microsoft SQL Server 09.00.3042

SQL客户端尝试过:
        Microsoft SQL Server Native Client版本10.00.5500(sqlncli10.dll,2007.100.5500.00)
        Microsoft SQL Native Client版本09.00.5000(sqlncli.dll,2005.90.5000.00)
        Microsoft SQL Server ODBC驱动程序版本03.85.1132(sqlsrv32.dll 2000.85.1132.0)

2 个答案:

答案 0 :(得分:3)

好的,我的问题的答案实际上是我搞砸了SQLBindParameter的电话。如果你查看我上面的代码,我的最后一个参数为NULL。仔细阅读文档 - 相信我,需要仔细阅读! - 显示如果最终参数为NULL,则将数据视为零终止。 (the documentation for SQLBindParameter说“如果StrLen_or_IndPtr是空指针,则驱动程序假定所有输入参数值都是非NULL ,并且该字符和二进制数据是以空值终止的。” - 强调我的并且,由于不幸的巧合,我提供的数据的第二个或第三个字节为零,因此实际存储的blob只有1或2个字节。不确定为什么它的尺寸小于8000 - 可能有一些尺寸&lt; 8000和各种驱动程序版本的相互作用,但我还没有花时间去挑逗它。

此外,在上面的代码中我说“如果我设置len1 = 0,因为某些(可怕的)文档似乎暗示,”。事实上,这是正确的事情。

因此正确的代码

SQLLEN len1 = 0;
SQLLEN nThisLen = (SQLLEN)sData.size();
SQLBindParameter( handle, (SQLUSMALLINT)4, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_VARBINARY, len1, 0, (SQLCHAR*)&sData.c_str(), nThisLen, &nThisLen );

答案 1 :(得分:0)

Jeff O走在正确的轨道上。尝试将你的sproc改为......

PROCEDURE [dbo].[spr_fff] 
    @act           AS INT
    ,@id           AS VARCHAR(255)
    ,@timestamp    AS DATETIME
    ,@preblob      AS nvarchar(MAX)

    DECLARE @blob varbinary(MAX) = CAST(@preblob as varbinary(MAX))
    /* Continue using varbinary blob as before */

请注意您的sproc参数数据类型的更改以及随后的转换为varbinary。

干杯。