2015-04-14 6 views
1

У меня есть файл на удаленной машине, который я хочу скопировать на хост-машину SQL Server в определенную область. Мне интересно, какие у меня варианты для этого, с помощью хранимой процедуры SQL Server, и, более конкретно, я хочу передать содержимое файла, а не сначала считывать все содержимое в память.Можно ли передать файл в хранимую процедуру SQL Server?

Я в основном ищу текшую версию этого:

CREATE PROCEDURE [dbo].[SaveFile] 
    (@filename nvarchar(255), @contents nvarchar(max)) 
AS 
BEGIN 
    DECLARE @ObjectToken INT 
    EXEC sp_OACreate 'ADODB.Stream', @ObjectToken OUTPUT 
    EXEC sp_OASetProperty @ObjectToken, 'Type', 1 
    EXEC sp_OAMethod @ObjectToken, 'Open' 
    EXEC sp_OAMethod @ObjectToken, 'WriteText', NULL, @contents 
    EXEC sp_OAMethod @ObjectToken, 'SaveToFile', NULL, 'C:\\Destination\\' + @filename, 2 
    EXEC sp_OAMethod @ObjectToken, 'Close' 
    EXEC sp_OADestroy @ObjectToken 
END 
  1. Могу ли я иметь filestream или что-то эквивалент в качестве сохраненного входного параметра процедуры?
  2. Есть ли хранимая процедура CLR обрабатывать поток?
  3. Возможно, одна процедура может открыть поток и вернуть @ObjectToken, другой мог WriteText кусок из потока, а третья процедура может SaveToFile и Close, но это, кажется, как !a.GoodIdea и я должен был бы обеспечить закрытие и разрушение через какой-то тайм-аут.
  4. Другие варианты?

Это время источников из C# консольного приложения, и я бы предпочел, чтобы поток этих больших файлов, а не что-то вроде File.ReadAllText(), загружая строку многогигабайтных в переменную, а затем вызов хранимой процедуры со всем содержимым файла.

+0

мои два цента, получить учетную запись Azure и использовать их API хранения. – ScarletMerlin

+0

Облачное хранилище Azure даже не является удаленной возможностью. – Ehryk

ответ

1

Я сделал несколько попыток получить эту работу с OLE Automation (sp_OACreate, sp_OAMethod и т. Д.) И столкнулся с рядом проблем и сделал решение на основе CLR.

У меня есть консольное приложение C#, хранимые процедуры C# CLR и образец базы данных SQL Server, размещенный на my github account в репозитории с именем StreamFile.

Основная идея заключается в том, что я вызываю процедуру инициирования передачи, которая регистрирует строку в базе данных и создает файл, посылает n фрагменты в другую хранимую процедуру, которая добавляется к файлу, а затем вызывает третью хранимую процедуру чтобы обозначить успешное завершение потоковой передачи.

CREATE PROCEDURE [dbo].[StreamFile_AddBytes] 
    (@fileID int, @chunk varbinary(max)) 
AS 
BEGIN 
BEGIN TRY 
    DECLARE @tmppath nvarchar(max) 
    SELECT @tmppath = FilePath FROM StreamedFiles WHERE StreamedFileID = @fileID 

    IF (@tmppath is null) 
     RAISERROR (N'Invalid StreamedFileID Provided: %d', 11, 1, @fileID); 

    --C# CLR Based Stored Procedure 
    EXEC dbo.AppendBytes @tmppath, @chunk 

    UPDATE StreamedFiles SET Chunks = Chunks + 1, FileSize = FileSize + LEN(@chunk) WHERE StreamedFileID = @fileID 

    SELECT * FROM StreamedFiles sf WHERE sf.StreamedFileID = @fileID 
END TRY 
BEGIN CATCH 
    DECLARE @ErrorMessage NVARCHAR(4000), @ErrorSeverity INT, @ErrorState INT; 
    SELECT @ErrorMessage = ERROR_MESSAGE(), @ErrorSeverity = ERROR_SEVERITY(), @ErrorState = ERROR_STATE(); 
    RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState); 
END CATCH 
0

Это возможное решение, что я буду испытывать:

CREATE PROCEDURE [dbo].[StreamOpen] 
AS 
BEGIN 
    DECLARE @ObjectToken INT 
    EXEC sp_OACreate 'ADODB.Stream', @ObjectToken OUTPUT 
    EXEC sp_OASetProperty @ObjectToken, 'Type', 1 
    EXEC sp_OAMethod @ObjectToken, 'Open' 
    SELECT @ObjectToken 
END 

CREATE PROCEDURE [dbo].[StreamAddChunk] (@token int, @chunk nvarchar(max)) 
AS 
BEGIN 
    EXEC sp_OAMethod @token, 'WriteText', NULL, @contents 
END 

CREATE PROCEDURE [dbo].[StreamClose] (@token int, @filename nvarchar(260)) 
AS 
BEGIN 
    EXEC sp_OAMethod @token, 'WriteText', NULL, @contents 
    EXEC sp_OAMethod @token, 'SaveToFile', NULL, 'C:\\Destination\\' + @filename, 2 
    EXEC sp_OAMethod @token, 'Close' 
    EXEC sp_OADestroy @token 
END 

Я буду обновлять этот ответ, как только он тестируется, и добавьте C# вызывающий код.

+0

Это не работает, так как все объекты OLE уничтожаются в конце партии. – Ehryk

Смежные вопросы