Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

SQL Server 2017 FileTables - How do I directly Insert files into a subdirectory?

Status
Not open for further replies.

Olaf Doschke

Programmer
Oct 13, 2004
14,847
DE
Talking about SQL Server 2017 FileTables.

I found a workaround to storing a file into a FileTable into a subdirectory of the FileStream share:
1. Store the file into root
2. update the path_location using the node.GetReparentedValue() method.

Code:
DECLARE @finalpath hierarchyid; 

Use pmanage_filetest2;
SELECT @finalpath = path_locator from dbo.Documents where name = 'Subfolder' AND path_locator.GetLevel() = 1; -- sub folders are all at level 1 in my case.

Insert Into dbo.Documents (name, file_stream) VALUES ('Newfile.xyz', ?) -- here the file itself comes in via query parameter, that works fine.
UPDATE dbo.Documents SET path_locator = path_locator.GetReparentedValue(0x, @finalpath) WHERE name = 'Newfile.xyz' AND path_locator.GetLevel() = 1;
The file name also comes in as parameter, I just don't want to make this unclear with multiple question marks and specify a hardcoded name here, instead.

By the way this can also be used to relocate from one SubDir to another, you'll just need another hierarchyid variable for the initial path, 0x is simply always the root path.

I will not use the root directory for permanent file storage, all files will go into subdirectories, nevertheless for the general case I fear just relying on being able to store a file with its name into an empty root folder only containing directories is not the best thing to do, if you reuse a path_locator you violate uniqueness of PK.

Other ways I found precompute the path_locator (it would be easy if you could set the parent_path_locator, but that's a computed column). Such a solution seems overcomplicated to me, for example, see The basis is an existing directory 'MyFiles', then doing:

Code:
DECLARE @path        HIERARCHYID
DECLARE @new_path    VARCHAR(675)

SELECT @path = path_locator 
FROM dbo.Documents
WHERE name = 'MyFiles' -- AND path_locator.GetLevel() = 1

SELECT @new_path = @path.ToString()     +
CONVERT(VARCHAR(20), CONVERT(BIGINT, SUBSTRING(CONVERT(BINARY(16), NEWID()), 1, 6))) + '.' +
CONVERT(VARCHAR(20), CONVERT(BIGINT, SUBSTRING(CONVERT(BINARY(16), NEWID()), 7, 6))) + '.' +
CONVERT(VARCHAR(20), CONVERT(BIGINT, SUBSTRING(CONVERT(BINARY(16), NEWID()), 13, 4))) + '/'
 
INSERT INTO dbo.Documents(name, file_stream, path_locator)
SELECT 'Notes2.txt', 0x, @new_path -- or whatever filename and filestream data, eg parameters

Not too much code, but because of NewID it can't be put into a sproc, I think it's a bit inconvenient. Also because it's white box code, making use of the knowledge about how path_locator values are represented in string format. that might change in later SQL Server versions.

Any idea how to make this more generic? You can only apply GetReparentedValue(0x, @finalpath) to an existing node in root, so even though my @finalpath is equal to @path and I don't need another path value but can use 0x, GetReparentedValue() doesn't work in an INSERT, you need a SELECT or UPDATE query with an existing path_locator value and thus the temporary storage into root, it seems.

Bye, Olaf.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top