繁体   English   中英

我可以将文件流式传输到SQL Server存储过程吗?

[英]Can I stream a file to a SQL Server stored procedure?

我在远程计算机上有一个文件,想要“复制”到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 ,另一个过程可以从流中@ObjectToken一个WriteText块,而第三个过程可以SaveToFileClose它,但这看起来像!a.GoodIdea ,我必须确保关闭和销毁通过某种超时。
  4. 还有其他选择吗?

它是从C#控制台应用程序中获取的,我更喜欢流式传输这些大文件,而不是像File.ReadAllText()类的东西,将一个数千兆字节的字符串加载到一个变量中,然后使用该文件的全部内容来调用存储过程。文件。

我做了一些尝试,以使其与OLE Automation( sp_OACreatesp_OAMethod等)一起工作,并遇到了许多问题,并提出了基于CLR的解决方案。

我有一个C#控制台应用程序,C#CLR存储过程和一个示例SQL Server数据库,该示例SQL Server数据库发布在名为StreamFile的存储库中的github帐户上。

基本思想是,我调用一个过程来启动传输,该过程将在数据库中记录一行并创建文件,将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

这是我将要测试的可能解决方案:

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#调用代码。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM