如何从 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 管道的所有列名及其数据类型?