2016-09-27 510 views
0

这是我程序返回@v_buffer变量的一部分。 问题是,我想要上传的文件大小大于8000字节。这就是为什么我需要使用varbinary(max)类型。 但sp_oamethod读取返回给我一个错误。 有人知道使用sp_oamethod解决我的问题很热吗?通过sp_oageterrorinfo返回Sp_oamethod上传大小大于8000的文件

declare @returnCode int 
declare @v_file int 
declare @v_buffer varbinary(max) 
declare @v_fullpath nvarchar(400) --pdf file phusical location 

exec @returncode = sp_oacreate 'adodb.stream', @v_file out 

exec @returncode = sp_oamethod @v_file, 'open' 

exec @returncode = sp_oasetproperty @v_file, 'type', 1 

exec @returncode = sp_oasetproperty @v_file, 'loadfromfile', @v_fullpath 


exec @returnCode = sp_oamethod @v_file, 'read', @v_buffer out, -1 
if @returncode <> 0 
begin 
    exec sp_oageterrorinfo @v_file 
end 

exec @returnCode = sp_OAMethod @v_file, 'Close' 
exec @returnCode = sp_OADestroy @v_file 

错误消息:

0x8004271A,ODSOLE扩展过程,在srv_convert错误。

回答

0

如果试图传递一个字符串,它是大于4000个字符,但小于或等于在长度8000个字符的使用sp_OASetProperty或到sp_OAMethod将向OLE自动化扩展存储的过程中,输入字符串被静默截断为4000在它传递给对象之前的字符并且不返回错误。

如果试图通过sp_OASetProperty OLE自动扩展存储过程将属性设置为大于8000个字符的字符串,或者如果尝试将输入参数传递给sp_OAMethod OLE自动扩展存储过程的时间超过8000个字符,您会收到以下错误信息:

hr   Source      Description 
    ---------- ---------------------------- -------------------------- 
    0x8004271A ODSOLE Extended Procedure Error in srv_convert. 

https://support.microsoft.com/en-us/kb/325492

1

请不要使用OLE自动化存储过程(即sp_OA*),因为它们已经从SQL Server 2005的发布弃用。对于SQLCLR(即SQL Server中存在的基于.NET的对象),您要做的事情非常简单。您可以创建一个标量函数来接受文件路径并使用File.ReadAllBytes方法返回其字节。通过SqlBytes类型返回byte[]

您需要将您的组件设置为PERMISSION_SET = EXTERNAL_ACCESS。为了做到这一点,请做而不是将数据库设置为TRUSTWORTHY ON,因为这是不必要的安全风险。相反,请使用密码对程序集进行签名,然后在DLL中为master数据库创建一个非对称密钥,然后从该密钥创建一个登录名,最后授予登录名EXTERNAL ACCESS ASSEMBLY权限。

有关使用SQLCLR的更多信息(包括许多示例),请参阅我在SQL Server Central上关于此主题撰写的一系列文章:Stairway to SQLCLR(该网站需要免费注册才能阅读其内容) 。或者,如果您不想处理任何编码,我创建了一个包含超过270个函数和存储过程的库,名为SQL#。有几个文件系统相关的功能,虽然它们都没有可用的免费版本。尽管如此,在这里可以提供帮助的是:File_GetFileBinary

+0

坦克的建议,但我不想使用任何其他工具比SQL Server。 我发现一个文件分割方法的解决方案,也适用于我的情况。 – Mat

+0

@Mat很好。需要说明的是,SQLCLR与'sp_OA *'存储过程一样多的SQL Server。您不需要[销售]我销售的[SQL#](http://SQLsharp.com/)产品,因为此特定功能很容易完成;它只有几行代码。程序集加载到数据库中,以便随数据一起备份(与扩展存储过程不同)。另外,SQLCLR比OLE Automation procs更高效更安全。他们可以使用新的数据类型,并且可以很容易地返回一个'VARBINARY(MAX)'。然后你可以这样做:'UPDATE tbl SET tbl.FileData = dbo.GetFile(tbl.path);'。 –

0

如果有人有同样的问题,我已经做了这样的: 在我的程序我创建临时#IMG表:

create table #IMG (FileID2 nvarchar(50), img image) 

如果文件大小大于8K,我在它的大小拆分零件8000和更新#IMG:

exec @returnCode = sp_oamethod @v_file, 'read', @v_buffer out, 8000 
    update #IMG set img = @v_buffer 
    SELECT @ptrval = TEXTPTR(Img) FROM #IMG WHERE FileID2 = @v_FileID2 

    --file split section 
    select @v_Blocks = @v_FileSize/8000+1 
    if @v_Blocks = 1 
    begin 
     WRITETEXT #IMG.Img @ptrval @v_buffer 
    end 
    else 
    begin 
     WRITETEXT #IMG.Img @ptrval @v_buffer 
     set @[email protected]_blocks-1 
     while @j>0 
     begin 
      exec @returnCode = sp_oamethod @v_file, 'read', @v_buffer out , 8000 
      set @i=(select DATALENGTH(Img) from #IMG WHERE FileID2= @v_FileID2) 
      UPDATETEXT #IMG.Img @ptrval @i 0 @v_buffer 
     set @[email protected] 
     end 
    end 
0

截至0x8004271A ODSOLE Extended Procedure Error in srv_convert.

描述你的情况,李您可以使用相同的解决方法NE

exec @returnCode = sp_oamethod @v_file, 'read', @v_buffer out, -1 

Create table #tmp(dt varbinary(max)) 

insert into #tmp 
exec @hr = sp_oamethod @v_file, 'read', @mode = -1 

Select dt from #tmp -- single column/single row. 
Drop Table #tmp -- clean up 

小心被替换:此代码是未经测试。然而,下面的代码工作正常,32KB XML输出:

Create table #tmp(dt xml) 

insert into #tmp 
exec @hr = sp_OAGetProperty @obj, 'responseXML.XML' 
/* 
    Here is the trick: inserting from the returned result set, i.e. 
    `insert into <table>(<columns>) select <columns>` 
*/ 

Select dt from #tmp -- single column/single row. 
Drop Table #tmp -- clean up 

responseXML.XML调用MSXML2.ServerXMLHttp.send后返回整个XML文档。该技巧根据sp_OAMethodResult Sets部分起作用。

table变量类型是可用的,该代码可以是甚至更短:

DECLARE @xml(val xml); 
insert into @xml 
exec @hr = sp_OAGetProperty @obj, 'responseXML.XML' 

Select * from @xml; -- just to see the output 

即没有必要清理。