2016-09-27 515 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 

即沒有必要清理。