Я использую функцию Split (найденную на social.msdn.com) и при выполнении вручную в окне запроса
SELECT * FROM dbo.Split('/ABC/DEF/GHI/JKL', '/')
получаю следующее
Id Name
-- ----
1
2 ABC
3 DEF
4 GHI
5 JKL
Где Id - это просто порядковый номер, обозначающий позицию в исходной строке, а Name - это имя этого узла.Иерархической информации пока нет.
Теперь, следующий шаг - поместить это в иерархическую структуру данных в БД.Я пытаюсь сделать это в хранимом процессе, и с моими навыками SQL, какими они являются, я попал в стену.Вот что я хотел бы иметь : (Обратите внимание, что приведенный выше столбец Id не связан со столбцом Id или ParentId.)
Id ParentId Name FullName
-- -------- ---- --------
1 NULL ABC /ABC
2 1 DEF /ABC/DEF
3 2 GHI /ABC/DEF/GHI
4 3 JKL /ABC/DEF/GHI/JKL
Я дошел до этого с моим SP (называемым GetId с параметром @FullName) - GetId должен возвращать Id, связанный с этим узлом.Если узел не существует, он должен быть создан, и должен быть возвращен Id из этой новой строки - другими словами, потребитель этого SP не должен заботиться или знать, существует ли узел до его вызова:
DECLARE @count int
-- // is there already a row for this node?
SELECT @count = COUNT(CatId)
FROM Category
WHERE FullName = @FullName
-- // if no row for this node, create the row
-- // and perhaps create multiple rows in hierarchy up to root
IF (@count = 0)
BEGIN
SELECT * FROM Split(@FullName, '/')
-- // NOW WHAT ???
-- // need to insert row (and perhaps parents up to root)
END
-- // at this point, there should be a row for this node
-- // return the Id associated with this node
SELECT Id
FROM Category
WHERE FullName = @FullName
Таблица категорий (список смежности), в которой эти элементы в конечном итоге окажутся через серию вставок, имеет следующую структуру.
CREATE TABLE Category (
Id int IDENTITY(1,1) NOT NULL PRIMARY KEY,
ParentId int NULL,
Name nvarchar(255) NOT NULL,
FullName nvarchar(255) NOT NULL)
В результате я не хочусгенерируйте значение для столбца Id в таблице Category и необходимо получить соответствующий ParentId для каждого узла.
После путей '/ ABC / DEF / GHI / JKL' и '/ ABC / DEF / XYZ /LMN / OPQ 'были обработаны, и я сделал SELECT * FROM Category, я бы ожидал увидеть следующее:
Id ParentId Name FullName
-- -------- ---- --------
1 NULL ABC /ABC
2 1 DEF /ABC/DEF
3 2 GHI /ABC/DEF/GHI
4 3 JKL /ABC/DEF/GHI
5 2 XYZ /ABC/DEF/XYZ
6 5 LMN /ABC/DEF/XYZ/LMN
7 6 OPQ /ABC/DEF/XYZ/LMN/OPQ
Q : можно ли будет перезвонить в SPрекурсивно, начиная с самого внешнего узла, до тех пор, пока узел не существовал или мы не стали конечным родителем?Что-то с эффектом:
GetId(@FullName)
{
If Category exists with @FullName
return CatId
Else // row doesn't exist for this node
Split @FullName, order by Id DESC so we get the leaf node first
Create Category row
@FullName,
@Name,
@ParentId = Id of next FullName (call GetId with FullName of next row from Split)
}