Создание подкаталога через SQL INSERT с использованием FileTable

Ранее Я спросил, как создать каталог вFileTable без использования File I / O API. Теперь я хочу создать подкаталог к родительскому каталогу, который я только что создал. Как назначить моего родителя во время вставки? Похоже, чтоparent_path_locator - вычисляемый столбец.

Это создает моего родителя ...

<code>INSERT INTO FileTable0 (name,is_directory,is_archive) VALUES ('Directory', 1, 0);
</code>

Как мне создать дочерний каталог для этого родителя в моей FileTable?

Ответы на вопрос(4)

Решение Вопроса

что я использовал для создания подкаталога, так какGetPathLocator() не будет генерировать новыйpath_locator ценность для меня - она будет интерпретировать только существующиеhierarchyids.

DECLARE @parentdir table(path hierarchyid not null);
DECLARE @subdir_locator hierarchyid

-- Create Parent Directory, OUTPUT inserted parent path
INSERT INTO FileTable0 (name,is_directory,is_archive) 
OUTPUT INSERTED.path_locator into @parentdir
SELECT 'Directory', 1, 0

-- Create new path_locator based upon parent
SELECT @subdir_locator = dbo.GetNewPathLocator(path) from @parentdir

-- Create Subdirectory
INSERT INTO FileTable0 (name,path_locator,is_directory,is_archive) 
VALUES ('subdirectory', @subdir_locator, 1, 0);

В приведенном выше блоке кода используется символ обнаруженное здесь значение path_locator который строит новыйhierarchyid представление из GUID использованиеnewid() метод и простой анализ). ФункцияGetNewPathLocator() не существует нигде в SQL Server, который я мог бы найти hierarchyid.GetDescendant() - самое близкое, что я мог найти, но он не использовал нативную структуру, на которую опирается FileTable). Может быть, в SQL.NEXT ...

CREATE FUNCTION dbo.GetNewPathLocator (@parent hierarchyid = null) RETURNS varchar(max) AS
BEGIN       
    DECLARE @result varchar(max), @newid uniqueidentifier  -- declare new path locator, newid placeholder       
    SELECT @newid = new_id FROM dbo.getNewID; -- retrieve new, GUID      
    SELECT @result = ISNULL(@parent.ToString(), '/') + -- append parent if present, otherwise assume root
                     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))) + '/'     
    RETURN @result -- return new path locator     
END
GO

ФункцияGetNewPathLocator() также требует представления SQLgetNewID для запросаnewid() используя трюк из этого поста.

create view dbo.getNewID as select newid() as new_id 

ЗвонитьGetNewPathLocator(), вы можете использовать параметр по умолчанию, который будет генерировать новыйhierarchyid или передать существующийhiearchyid строковое представление .ToString()) создать ребенкаhierarchyid как видно ниже ...

SELECT dbo.GetNewPathLocator(DEFAULT); -- returns /260114589149012.132219338860058.565765146/
SELECT dbo.GetNewPathLocator('/260114589149012.132219338860058.565765146/'); -- returns /260114589149012.132219338860058.565765146/141008901849245.92649220230059.752793580/

нимые процедуры в виде кода C #.

Я только что создал проект интеграции GitHub CLR для этого.https: //github.com/rhyous/Db.FileTableFramewor

У него есть различные функции или процедуры, которые вы хотели бы: CreateFile, CreateDirectory, DirectoryExists. И на GitHub он, конечно, может быть изменен и улучшен кем угодно.

чтобы пытаться воссоздать иерархию в коде, я решил обновить path_locator после того, как SQL создал собственный идентификатор:

DECLARE @pathID hierarchyid;
DECLARE @parentdir table(path hierarchyid not null);

IF NOT EXISTS(SELECT 1 FROM FileAsset WHERE is_directory = 1 AND file_stream.GetFileNamespacePath() = '\Assets\Test')
INSERT INTO FileAsset (name, is_directory) VALUES( 'Test', 1)

SELECT @pathID = FileAsset.path_locator FROM FileAsset WHERE file_stream.GetFileNamespacePath() = '\Assets\Test'

INSERT INTO FileAsset (name, file_stream) OUTPUT INSERTED.path_locator into @parentdir VALUES('MyDoc.txt', 0x)

UPDATE FileAsset SET path_locator = '/' + REPLACE(@pathID.ToString(), '/','') + path_locator.ToString() WHERE path_locator = (SELECT [path] FROM @parentdir)

Где 'Assets' - это имя моего каталога FileTable, 'Test' - это имя каталога, в который я хочу поместить свой файл, 'MyDoc.txt' - это имя файла, а 0x - нулевая запись для файлового потока.

Я уверен, что собираюсь превратить это в функцию, достаточно просто.

Видеть..

CREATE PROCEDURE InsertFileAsset

    @fileName varchar(255),
    @dirName varchar(255),
    @data varbinary(MAX),
    @stream_id uniqueidentifier OUTPUT
AS
BEGIN
    DECLARE @pathID hierarchyid;
    DECLARE @parentdir table(path hierarchyid not null);
    DECLARE @streamID table(streamID uniqueidentifier not null);

    IF NOT EXISTS(SELECT 1 FROM FileAsset WHERE is_directory = 1 AND file_stream.GetFileNamespacePath() = '\Assets\' + @dirName)
    INSERT INTO FileAsset (name, is_directory) VALUES( @dirName, 1)

    SELECT @pathID = FileAsset.path_locator FROM FileAsset WHERE file_stream.GetFileNamespacePath() = '\Assets\' + @dirName

    INSERT INTO FileAsset (name, file_stream) OUTPUT INSERTED.path_locator into @parentdir VALUES(@fileName, @data)

    UPDATE FileAsset SET path_locator = '/' + REPLACE(@pathID.ToString(), '/','') + path_locator.ToString() OUTPUT inserted.stream_id INTO @streamID WHERE path_locator = (SELECT [path] FROM @parentdir)

    SELECT @stream_id = streamID FROM @streamID

    RETURN
END
GO
 Tod11 июн. 2015 г., 10:30
После некоторого тщательного тестирования кажется, что оператор обновления склонен к тупикам, когда он вызывается параллельно.

Функция возвращает иерархию вместо строки

Если есть родительский объект, функцияierarchyid :: GetReparentedValue используется для генерации нового идентификатора вместо конкатенации строк.

create function doc.GetNewPathLocator (@parent hierarchyid = null) returns hierarchyid
as
begin 
    declare @id uniqueidentifier = (select new_id from dbo.GetNewID);
    declare @path hierarchyid = (convert(hierarchyid, '/' + 
            convert(varchar(20), convert(bigint, substring(convert(binary(16), @id), 1, 6))) + '.' +     
            convert(varchar(20), convert(bigint, substring(convert(binary(16), @id), 7, 6))) + '.' +     
            convert(varchar(20), convert(bigint, substring(convert(binary(16), @id), 13, 4))) + '/'));
    return case when @parent is null then @path else @path.GetReparentedValue(hierarchyid::GetRoot(), @parent) end;
end
go

Ваш ответ на вопрос