如何从 blob 文件夹中选择 SQL Server 数据库的所有文件?

Posted

技术标签:

【中文标题】如何从 blob 文件夹中选择 SQL Server 数据库的所有文件?【英文标题】:How to select all files of a SQL Server database from blob folder? 【发布时间】:2020-06-09 09:38:49 【问题描述】:

我有一个 SQL Server 数据库。

您可以使用以下脚本创建类似的数据库:

CREATE DATABASE [test]
CONTAINMENT = NONE
ON PRIMARY 
   (NAME = N'test', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL14.SQLEXPRESS\MSSQL\DATA\test.mdf' , SIZE = 8192KB , MAXSIZE = UNLIMITED, FILEGROWTH = 65536KB ), 
   FILEGROUP [FS] CONTAINS FILESTREAM  DEFAULT
   (NAME = N'FS', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL14.SQLEXPRESS\MSSQL\DATA\FS' , MAXSIZE = UNLIMITED)
   LOG ON 
   (NAME = N'test_log', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL14.SQLEXPRESS\MSSQL\DATA\test_log.ldf', SIZE = 8192KB, MAXSIZE = 2048GB, FILEGROWTH = 65536KB )
GO

如何选择所有数据库文件已经很清楚了:

select * from sys.database_files

file_id     file_guid                            type type_desc                                                    data_space_id name                                                                                                                             physical_name                                                                                                                                                                                                                                                    state state_desc                                                   size        max_size    growth      is_media_read_only is_read_only is_sparse is_percent_growth is_name_reserved is_persistent_log_buffer create_lsn                              drop_lsn                                read_only_lsn                           read_write_lsn                          differential_base_lsn                   differential_base_guid               differential_base_time  redo_start_lsn                          redo_start_fork_guid                 redo_target_lsn                         redo_target_fork_guid                backup_lsn
----------- ------------------------------------ ---- ------------------------------------------------------------ ------------- -------------------------------------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ----- ------------------------------------------------------------ ----------- ----------- ----------- ------------------ ------------ --------- ----------------- ---------------- ------------------------ --------------------------------------- --------------------------------------- --------------------------------------- --------------------------------------- --------------------------------------- ------------------------------------ ----------------------- --------------------------------------- ------------------------------------ --------------------------------------- ------------------------------------ ---------------------------------------
1           07DE2F09-B9C3-4CC9-AC7F-C7BBEDBFE572 0    ROWS                                                         1             test                                                                                                                             C:\Program Files\Microsoft SQL Server\MSSQL14.SQLEXPRESS\MSSQL\DATA\test.mdf                                                                                                                                                                                     0     ONLINE                                                       1024        -1          8192        0                  0            0         0                 0                0                        NULL                                    NULL                                    NULL                                    NULL                                    NULL                                    NULL                                 NULL                    NULL                                    NULL                                 NULL                                    NULL                                 NULL
2           25C00910-F2F0-48EF-8AE6-DB3E947DF0F3 1    LOG                                                          0             test_log                                                                                                                         C:\Program Files\Microsoft SQL Server\MSSQL14.SQLEXPRESS\MSSQL\DATA\test_log.ldf                                                                                                                                                                                 0     ONLINE                                                       1024        268435456   8192        0                  0            0         0                 0                0                        NULL                                    NULL                                    NULL                                    NULL                                    NULL                                    NULL                                 NULL                    NULL                                    NULL                                 NULL                                    NULL                                 NULL
65537       DB6C446D-E1E1-4F5B-BC27-92168A94A92B 2    FILESTREAM                                                   2             FS                                                                                                                               C:\Program Files\Microsoft SQL Server\MSSQL14.SQLEXPRESS\MSSQL\DATA\FS                                                                                                                                                                                           0     ONLINE                                                       0           -1          0           0                  0            0         0                 0                0                        36000000012900001                       NULL                                    NULL                                    NULL                                    NULL                                    NULL                                 NULL                    NULL                                    NULL                                 NULL                                    NULL                                 NULL

(3 rows affected)

现在让我们创建一个带有 blob 的表:

USE [test]

CREATE TABLE TestBlob
(
    [Id] [uniqueidentifier] ROWGUIDCOL NOT NULL UNIQUE, 
    [tbBin] VARBINARY(MAX) FILESTREAM NULL
)
GO

然后放一些数据:

USE [test]

INSERT INTO TestBlob (Id, tbBin)
    SELECT NEWID(), BulkColumn FROM OPENROWSET(Bulk 'C:\Everyone\small', Single_Blob) AS tb 

INSERT INTO TestBlob (Id, tbBin)
    SELECT NEWID(), BulkColumn FROM OPENROWSET(Bulk 'C:\Everyone\another', Single_Blob) AS tb 

现在 blob 文件夹如下所示:

cmd> tree "C:\Program Files\Microsoft SQL Server\MSSQL14.SQLEXPRESS\MSSQL\DATA\FS" /F

C:\PROGRAM FILES\MICROSOFT SQL SERVER\MSSQL14.SQLEXPRESS\MSSQL\DATA\FS
│   filestream.hdr
│
├───$FSLOG
└───f4bf1197-bb52-4246-95ba-4b7622065c19
    └───4cf08168-3853-4c3d-ada2-4a1ff8d19900
            00000024-000000b1-0002
            00000024-000000cd-0002

我需要一个 T-SQL 查询来选择数据库的所有 blob 文件。

这是以下文件(我的数据库使用它们):

00000024-000000b1-0002
00000024-000000cd-0002

有人可以帮我吗?

我也知道可以使用未记录的存储过程:

EXEC master.sys.xp_dirtree 'C:\PROGRAM FILES\MICROSOFT SQL SERVER\MSSQL14.SQLEXPRESS\MSSQL\DATA\FS',0,1;

subdirectory                                                                                                                                                                                                                                                     depth       file
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ----------- -----------
$FSLOG                                                                                                                                                                                                                                                           1           0
f4bf1197-bb52-4246-95ba-4b7622065c19                                                                                                                                                                                                                             1           0
4cf08168-3853-4c3d-ada2-4a1ff8d19900                                                                                                                                                                                                                             2           0
00000024-000000b1-0002                                                                                                                                                                                                                                           3           1
00000024-000000cd-0002                                                                                                                                                                                                                                           3           1
filestream.hdr                                                                                                                                                                                                                                                   1           1

(6 rows affected)

但它适用于文件系统。我的意思是它不考虑数据库是否使用文件。

【问题讨论】:

"我需要一个 t-sql 查询来选择数据库的所有 blob 文件。"为什么? 你为什么要这个?这不仅仅是一个 blob,它正在使用文件流存储。否则它将存储在数据库数据文件中。只需查询表将返回 blob。这些文件的位置是众所周知的,实际上它是在安装期间指定的。例如,没有理由将它们存储在 Program Files 中。 如果您想将这些文件作为文件读取,您可以通过您使用的 SQL 客户端库来实现。例如,对于 ADO.NET,you can use SqlFileStream。你不需要知道他们的路径。 @DavidBrowne-Microsoft 一般来说,我需要将数据库使用的每个文件同步到某个存储 这将是可能的并且支持使用 FileTable,但不是 FileStream。 docs.microsoft.com/en-us/sql/relational-databases/blob/… 【参考方案1】:

您可能已经注意到,您的 blob 存储在 GUID 中的两个文件夹中。

f4bf1197-bb52-4246-95ba-4b7622065c19 是您的表格参考 4cf08168-3853-4c3d-ada2-4a1ff8d19900 是您的专栏参考

如果您有多个 blob,那么您将有多个子文件夹。

您可能可以从这篇文章中得出一个查询。

https://www.sqlskills.com/blogs/paul/filestream-directory-structure-where-do-the-guids-come-from/

SELECT
    [o].[name] AS [Table],
    [cp].[name] AS [Column],
    [p].[partition_number] AS [Partition],
    [r].[rsguid] AS [Rowset GUID],
    [rs].[colguid] AS [Column GUID]
FROM sys.sysrowsets [r] CROSS APPLY sys.sysrscols [rs]
JOIN sys.partitions [p]
    ON [rs].[rsid] = [p].[partition_id]
JOIN sys.objects [o]
    ON [o].[object_id] = [p].[object_id]
JOIN sys.syscolpars [cp]
    ON [cp].[colid] = [rs].[rscolid]
WHERE [rs].[colguid] IS NOT NULL
    AND [o].[object_id] = [cp].[id]
    AND [r].[rsguid] IS NOT NULL
    AND [r].[rowsetid] = [rs].[rsid];
GO

请注意,在新的 sql server 版本中,基表不再容易获得。

我建议考虑使用其他用户评论的文件表。

下面的文章将告诉你如何开始。

https://www.sqlshack.com/sql-server-filetable-the-next-generation-of-sql-filestream/

SQL Server 将完成后续工作并将您的文件组呈现为文件夹和文件。 你文件表的权限会被镜像到共享文件夹

或者您可以继续使用您的 master.sys.xp_dirtree 技术。

https://www.patrickkeisler.com/2012/11/how-to-use-xpdirtree-to-list-all-files.html

假设您需要的是一个文件和 3 深,并且是文件,因为 $FSLOG 是 2 深

DECLARE @DirectoryTree TABLE (
    id INT IDENTITY(1, 1)
    ,subdirectory NVARCHAR(512)
    ,depth INT
    ,isfile BIT
    );

INSERT INTO @DirectoryTree
EXEC master.sys.xp_dirtree 'C:\PROGRAM FILES\MICROSOFT SQL SERVER\MSSQL14.SQLEXPRESS\MSSQL\DATA\FS'
    ,3
    ,1

SELECT *
FROM @DirectoryTree
WHERE depth = 3
    AND isfile = 1

请记住,您可能会得到重复的文件 ID。请考虑使用 FileTable 替代方案。

【讨论】:

这实际上与我在问题中提出的相同。请参阅我的问题的最后一部分。这种方法不能保证我通过执行 xp_dirtree EXEC 获得的文件正​​在使用中。换句话说,任何人都可以去 blob 文件夹并把与 db 无关的文件放在那里 @isxaker 任何人都应该能够做到这一点。首先,任何人都不应该拥有该文件夹的权限,除非管理员故意公开它。即使那样,它也应该只是读取权限。您不能要求数据库修复不良的管理实践 @PanagiotisKanavos 是的,这很公平。也许我不关心这种情况。但是这个答案中的代码与我在问题中提供的完全一样 @isxaker 点击链接。如果您“为文件 I/O 访问启用 FILESTREAM”和其他设置。如果您已正确完成所有操作,您的文件将被列为共享文件夹...您当前显示的是原始数据库文件。不是实际的文件。 tsql 将它们重命名为 GUID 并将它们存储在层次结构中。 xp_dirtree 只是一个命令 shell 命令,它列出服务器上任何路径的文件。 @FrankChen 当然,我什至在写问题之前就启用了它=)实际上是必需的。请检查我的问题的底部。它包含 master.sys.xp_dirtree 的用法和输出。我的意思是我已经知道了。但不幸的是,这对我来说还不够。

以上是关于如何从 blob 文件夹中选择 SQL Server 数据库的所有文件?的主要内容,如果未能解决你的问题,请参考以下文章

使用 ashx 处理程序从 SQL 表中读取 BLOB 文件时如何在 Edge 中查看文件

如何使用 BCP 或 Sql Server Management Studio 从 Sql Server 中获取 BLOB 数据?

如何从使用 Ionic 框架中的相机插件选择的视频文件 URI 创建 Blob?

如何从 Azure SQL 数据库中的 Blob 解析 Json

如何从加载在 sql/plsql 表中的 csv 文件中获取值

如何从 Blob 中的 CSV 文件在 SQL 数据库中创建一个表,其中包含通过数据流或 ADF 管道的所有列名及其数据类型?