我可以将文件流式传输到 SQL 服务器存储过程吗?
Can I stream a file to a SQL Server stored procedure?
我在远程机器上有一个文件,我想 'copy' 到 SQL 服务器主机的特定区域。我想知道通过 SQL 服务器存储过程我有什么选择,更具体地说,我想流式传输文件内容,而不是先将整个内容读入内存。
我基本上是在寻找这个的流媒体版本:
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
- 我可以使用
filestream
或类似的东西作为存储过程输入参数吗?
- 是否有 CLR 存储过程处理流?
- 也许一个过程可以打开流和 return
@ObjectToken
,另一个可以 WriteText
来自流的块,第三个过程可以 SaveToFile
和 Close
它,但这看起来像 !a.GoodIdea
,我必须通过某种超时来确保关闭和销毁。
- 其他选项?
它来自 C# 控制台应用程序,我更喜欢流式传输这些大文件而不是像 File.ReadAllText()
那样的东西,将数 GB 的字符串加载到变量中,然后调用存储过程文件的全部内容。
这是我将要测试的可能解决方案:
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# 调用代码。
我做了一些尝试来使它与 OLE 自动化(sp_OACreate
、sp_OAMethod
等)和 运行 一起工作,并解决了许多问题,并制作了一个基于 CLR 的解决方案。
我有一个 C# 控制台应用程序、C# CLR 存储过程和一个示例 SQL 服务器数据库发布在 my github account in repository named StreamFile。
基本思想是我调用一个过程来启动 t运行sfer,它在数据库中记录一行并创建文件,将 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
我在远程机器上有一个文件,我想 'copy' 到 SQL 服务器主机的特定区域。我想知道通过 SQL 服务器存储过程我有什么选择,更具体地说,我想流式传输文件内容,而不是先将整个内容读入内存。
我基本上是在寻找这个的流媒体版本:
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
- 我可以使用
filestream
或类似的东西作为存储过程输入参数吗? - 是否有 CLR 存储过程处理流?
- 也许一个过程可以打开流和 return
@ObjectToken
,另一个可以WriteText
来自流的块,第三个过程可以SaveToFile
和Close
它,但这看起来像!a.GoodIdea
,我必须通过某种超时来确保关闭和销毁。 - 其他选项?
它来自 C# 控制台应用程序,我更喜欢流式传输这些大文件而不是像 File.ReadAllText()
那样的东西,将数 GB 的字符串加载到变量中,然后调用存储过程文件的全部内容。
这是我将要测试的可能解决方案:
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# 调用代码。
我做了一些尝试来使它与 OLE 自动化(sp_OACreate
、sp_OAMethod
等)和 运行 一起工作,并解决了许多问题,并制作了一个基于 CLR 的解决方案。
我有一个 C# 控制台应用程序、C# CLR 存储过程和一个示例 SQL 服务器数据库发布在 my github account in repository named StreamFile。
基本思想是我调用一个过程来启动 t运行sfer,它在数据库中记录一行并创建文件,将 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