如何使用T-SQL从varbinary列下载文件

时间:2019-04-03 01:29:44

标签: sql sql-server tsql

我正在使用SQL Server2016。我有一个表file_data,其中的列 data varbinary类型。

CREATE TABLE [dbo].[file_data]
(
    [file_data_id] [INT] IDENTITY(1,1) NOT NULL,
    [file_name] [VARCHAR](20) NOT NULL,
    [description] [VARCHAR](255) NOT NULL,
    [data] [VARBINARY](MAX) FILESTREAM  NOT NULL,
    [file_guid] [UNIQUEIDENTIFIER] ROWGUIDCOL  NOT NULL,

    CONSTRAINT [pk_file_data] 
        PRIMARY KEY CLUSTERED ([file_data_id] ASC)
                    WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, 
                          IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, 
                          ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] FILESTREAM_ON [filestream],
    UNIQUE NONCLUSTERED ([file_guid] ASC)
                    WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, 
                          IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, 
                          ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] FILESTREAM_ON [filestream]
GO

数据列存储1个文件,通常为txt文件。因此,该表具有多个行。

如何使用T-SQL从 data 列中下载任意1行的文件?我正在使用Microsoft SQL Server Management Studio。

1 个答案:

答案 0 :(得分:1)

编辑:我只是重新阅读了您的问题,但我认为这个问题错了...

行,因此该表有多行吸引了我...

如果您只想将表的列的二进制内容发送到文件系统,则可以使用BCP(请参阅链接的答案,请记住,这在您的帐户下不会起作用,因此访问权限和目标目录可能不是您所期望的)。但是我会使用一些外部工具(可能是powershell),连接到数据库,然后简单地将内容读取到文件中。

我不会删除以前的答案,因为它也可以帮助您。

我敢肯定,T-SQL是错误的工具。我的回答可能会对您有所帮助,它至少会显示一些原理...

BLOB列(在您的情况下为VARBINARY(MAX))仅是毫无意义的字节链。 SQL Server不知道如何将其解释为有意义的数据。

我使用一个简单的字符串变量来 mockup 一个文件的内容:

DECLARE @TestText VARCHAR(MAX)=
N'This is the first line
This is the second line';

-现在,此字符串将转换为varbinary并分配给BLOB变量。
-从原理上讲,这就是您专栏中的内容

DECLARE @YourFileStore VARBINARY(MAX)=CAST(@TestText AS VARBINARY(MAX));
SELECT @YourFileStore;

-您回来了

0x5468697320697320746865206669727374206C696E650D0A5468697320697320746865207365636F6E64206C696E65

-这是一个十六进制字符串,其中每两位数字代表一个字符(54是T,68是h,依此类推。
-在中间的某个地方,您会发现序列0D0A,即换行符。
-只要我们知道如何解释二进制文件,我们就可以简单地将其重新转换为前一种类型。这将使之前的字符串返回:

SELECT CAST(@YourFileStore AS VARCHAR(MAX));

-逐行读取此 将需要在换行符处进行字符串拆分。
-您未声明SQL Server的版本。在这里,我使用OPENJSON(需要v2016 +)。

SELECT *
FROM OPENJSON('["' + REPLACE(CAST(@YourFileStore AS VARCHAR(MAX)),CHAR(13)+CHAR(10),'","') + '"]');

什么时候对您有用:

如果所有BLOB具有相同的内容(结构上)并且SQL Server可以使用简单的CASTCONVERT来实现有意义的数据类型,这可能对您有用。

什么时候对您不起作用:

如果文本文件不是简单的UCS-2(几乎与UTF-16相同),则转换为NVARCHAR(MAX)纯ASCII ,其转换为{{ 1}}。

任何编码(如VARCHAR(MAX)),错误的 endian 或ASCII> 127(查找 collat​​ions )都可能只返回垃圾。

您应该做什么:

如果这种简单的转换帮助您-很好-则您很幸运。如果没有,则应该使用其他功能更强大的字符串处理工具。

您应该始终以适当的类型存储数据。 BLOB用于存储数据,您可以不想在内部查看(如图片)。您的数据应存储在单独的行中,并具有通用ID和行号,以重新创建全文。