我正在开发这个应用程序,其中我需要将大型数据文件上传到我的SQL Server DB,并且我一直在使用FileStream来更高效地完成这项工作。
我知道这些文件直接存储在我系统的文件夹中(C:\CryptoDB)。
问题是,我需要操作这些文件(解密它们),但我无法恢复它们的文件路径。这样做,我将能够直接操作它们,而不必通过SQL重新下载它们,这真的是一种浪费。
到目前为止,我所能做的是:
我的表格:
CREATE TABLE [arquivo] (
[idUsuario] INT NOT NULL,
[fileState] INT NOT NULL,
[fileContent] varbinary(max) FILESTREAM,
[fileName] VARCHAR (150) NULL,
[fileSize] VARCHAR (50) NULL,
id UNIQUEIDENTIFIER ROWGUIDCOL NOT NULL UNIQUE,
CONSTRAINT [FK_arquivo_usuario] FOREIGN KEY ([idUsuario]) REFERENCES usuario(id)
);插入:
Insert into arquivo(id, idUsuario, fileState, fileContent, fileName, fileSize) Values(
newId(),
1,
5,
(SELECT * FROM OPENROWSET(BULK 'c:\medio.jpeg', SINGLE_BLOB) AS varbinary(max)) ,
'medio.jpeg',
'123'
)当我尝试恢复文件路径时:
DECLARE @filePath varchar(max)
SELECT @filePath = fileContent.PathName()
FROM arquivo
PRINT @filepath我得到的结果是:
\\TEHORT-PC\MSSQLSERVER\v02-A60EC2F8-2B24-11DF-9CC3-AF2E56D89593\CryptoDB\dbo\arquivo\fileContent\31E3697E-0576-4B0F-B0AA-6E046F4116A1\VolumeHint-HarddiskVolume2文件的实际位置:
C:\CryptoDB\DATA\902a7d8d-c8c1-43b0-8c94-b12319293f42\7febdbd1-02c6-4b00-aa3c-a72bee80ef9c\发布于 2016-05-29 18:22:37
获取所有FILESTREAM数据的物理位置的
SELECT t.name AS 'table',c.name AS 'column',fg.name AS‘文件组名’,dbf.type_desc AS 'type_description',dbf.physical_name AS 'physical_location‘FROM sys.filegroups fg INNER JOIN sys.database_files dbf ON fg.data_space_id = dbf.data_space_id INNER JOIN sys.tables t ON fg.data_space_id = t.filestream_data_space_id INNER JOIN sys.columns c ON t.object_id = c.object_id AND c.is_filestream = 1
All FILESTREAM BLOB-fields query result sample
选择o.name作为表,选择cp.name作为列,选择r.rsguid作为行集GUID,
2.1。查询结果:
表:文档
《专栏》: DIGITAL_FILE
行集GUID: 0x6AA5E6045794D34D8B1FAC0F49A49B0A
列GUID: 0xD756E638FB2CC843AE98F489B57F6D7D
根据此guids计算子路径:
0x6AA5E6045794D34D8B1FAC0F49A49B0A等于以下路径: 04e6a56a-9457-4dd3-8b1f-ac0f49a49b0a
反向6AA5E604-反向5794-反向D34D-反向8B1F-原始AC0F49A49B0A
0xD756E638FB2CC843AE98F489B57F6D7D等于此路径: 38e656d7-2cfb-43c8-ae98-f489b57f6d7d (前面guid解析中的规则)
2.2 FILESTREAM存储的计算结果完整路径:
SQL i:\SQL FileStreams\GTMK\GTM_FILE_STREAM\04e6a56a-9457-4dd3-8b1f-ac0f49a49b0a\38e656d7-2cfb-43c8-ae98-f489b57f6d7d
posc_astrachan
在NTFS-folder.中获取BLOB-value的
3.1。用于查询高级SQL Server页面信息的存储过程
SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[procDBCC_PAGE]
@db_name varchar (500),
@filenum INT,
@pagenum INT
AS
BEGIN
SET NOCOUNT ON
DBCC TRACEON (3604);
DBCC PAGE (@db_name, @filenum, @pagenum, 3) WITH TABLERESULTS;
SET NOCOUNT OFF
END3.2。用于查询FILESTREAM的BLOB的原始文件名的存储过程-表的字段
SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[procFindLogSequenceNumber]
-- @TableName varchar (500),
@instanceS varchar (19), -- key value for filed INSTANCE_S
@tableName varchar(500), -- DOCUMENT
@keyFieldName varchar(500), -- INSTANCE_S
@LogSequenceNumber varchar (500) OUTPUT
AS
SET NOCOUNT ON
DECLARE @db_name varchar (500)
DECLARE @filenum INT
DECLARE @pagenum INT
DECLARE @slotnum INT
DECLARE @rid varchar (100)
DECLARE @ridDotted varchar (100)
DECLARE @parent_object varchar (500)
DECLARE @sql nvarchar(2000)
DECLARE @sqlTable Table(physloc varchar(100))
DECLARE @DBCC_PAGE_Output Table ([ParentObject] varchar (MAX), [Object] varchar (MAX), [Field] varchar (MAX), [VALUE] varchar (MAX))
SET @db_name = db_name()
SET @sql = 'SELECT top 1 sys.fn_PhysLocFormatter (%%physloc%%) AS [PhysicalRID] FROM '+@tableName+' WHERE '
+@keyFieldName+' = '''+@instanceS+''''
INSERT @sqlTable (physloc)
EXECUTE sp_executesql @sql
SET @rid = (select top 1 physloc from @sqlTable)
if @rid is NULL
BEGIN
RETURN -1;
END
-- parse (@rid): (1:1172779:6) 1-@filenum, 2- @pagenum, 3- @slotnum
SET @ridDotted = Replace(@rid, ':', '.');
SET @ridDotted = Replace(@ridDotted, '(', '');
SET @ridDotted = Replace(@ridDotted, ')', '');
SET @filenum = (SELECT Parsename(@ridDotted, 3))
SET @pagenum = (SELECT Parsename(@ridDotted, 2))
SET @slotnum = (SELECT Parsename(@ridDotted, 1))
INSERT @DBCC_PAGE_Output ([ParentObject], [Object], [Field], [VALUE])
EXECUTE procDBCC_PAGE @db_name, @filenum , @pagenum
SET @parent_object = (SELECT TOP 1 [ParentObject] FROM @DBCC_PAGE_Output WHERE [Field] = 'INSTANCE_S'
AND [VALUE] = @instanceS)
--CreateLSN field Only
SET @LogSequenceNumber = (SELECT [VALUE] FROM @DBCC_PAGE_Output WHERE
[ParentObject] = @parent_object AND
[Field] = 'CreateLSN'
)
if @LogSequenceNumber is NULL
BEGIN
RETURN -1;
END
-- result 0006c050:00000120:0090 (442448:288:144)
-- clear (...)
SET @LogSequenceNumber = Replace(@LogSequenceNumber, ' ', '.');
SET @LogSequenceNumber = (SELECT Parsename(@LogSequenceNumber, 2))
--replace ":" to "-"
SET @LogSequenceNumber = Replace(@LogSequenceNumber, ':', '-');
SET NOCOUNT OFF3.3。BLOB的NTFS文件夹上get filename的存储过程查询示例:
declare @filestreamFileName varchar(500);
exec procFindLogSequenceNumber 'ZW_NU9hGZ0CKoSXYAoc', 'DOCUMENT', 'INSTANCE_S', @filestreamFileName OUTPUT
select @filestreamFileName3.4。结果( NTFS文件夹中的原始文件名):
0003137a-00001244-00d0
3.5。结果完整路径:
SQL i:\SQL FileStreams\GTMK\GTM_FILE_STREAM\04e6a56a-9457-4dd3-8b1f-ac0f49a49b0a\38e656d7-2cfb-43c8-ae98-f489b57f6d7d\0003137a-00001244-00d0
posc_astrachan
发布于 2015-04-13 16:47:28
你得到的路径是正确的,你应该得到网络共享路径,而不是本地路径,并使用SqlFileStream打开一个流。
https://msdn.microsoft.com/en-us/library/system.data.sqltypes.sqlfilestream%28v=vs.110%29.aspx
你也可以使用OpenSqlFilestream方法获得一个文件句柄,即在Windows API中使用它。
发布于 2016-09-17 01:16:19
Alexander的回答很好,省去了我将页/槽编号与实际LSN关联起来的很多麻烦。在我使用SQL Server2008 R2的情况下,我必须对他的SP进行一些调整才能使其正常工作,这些是:
SP的第一个参数:
@instanceS varchar (100),--已归档INSTANCE_S
的键值
在我的例子中,这是一个唯一的标识符,所以我需要一个更大的varchar,原始值是19。
当查询DBCC页面输出时:
设置@parent_object = (SELECT TOP 1 ParentObject FROM @DBCC_PAGE_Output WHERE 字段=@键字段名= @instanceS)实例
它最初声明了"[Field] = 'INSTANCE_S'",这显然是硬编码了一个值,这个值对OP有效,但对我不起作用。它需要与FILESTREAM表的键字段的名称匹配。
另外,为了澄清一下SPs input params:
@instanceS =标识行的实际列值。这是否总是与设置为表的"RowGuid“的列相匹配?
@tableName =非常清楚。FILESTREAM表的名称。
@keyFieldName =表的键列的名称。应该是获取@instanceS的源列。
https://stackoverflow.com/questions/19627437
复制相似问题