我是SQL新手,希望对以下问题有任何帮助。我有以下代码为节点和树创建一个表,但不知道如何在我的代码中实现以下规则。
create table Node(
NodeId int not null,
ParentId int null,
NodeName varchar(255) not null,
constraint PK_Node primary key(NodeId),
constraint UK_NodeName unique(NodeName)
)
go
create table Tree(
NodeId int not null,
ParentId int not null,
Level int not null,
constraint PK_Tree primary key(NodeId, ParentId),
constraint UK_Level unique(NodeId, Level)
)
go}
alter table Node
add constraint FK_NodeNode foreign key(ParentId) references Node(NodeId) --on delete cascade;
alter table Tree
add constraint FK_NodeTreeNode foreign key(NodeId) references Node(NodeId) on delete cascade;

想象一下具有以下属性的树结构:
创建表和索引以存储此信息和过程,以尽可能高效地执行以下操作:
答案 0 :(得分:2)
并非所有约束都可以在SQL Server中设置。 a,d,e,f的逻辑应该适用于应用程序。
树只是Nodes
的组合。所以我们只需要定义Node
的存储空间。
create table Node(
NodeId int not null identity(1,1), -- Identity, auto generate Id for new Node
ParentId int null, -- If null, it is the root of the tree
MaxChild int not null default(-1),
NodeName varchar(255) not null,
constraint PK_Node primary key(NodeId),
constraint UK_NodeName unique(NodeName),
constraint FK_Node foreign key(ParentId) references Node(NodeId)
-- How the `Node` to be related and form the tree can be done
-- by adding the `Foreign Key` of `Node` itself
-- A node cannot be simply deleted if it is a parent.
)
添加节点:
-- Add root
insert Node (NodeName) VALUES ('root')
-- Add child
insert Node (ParentId, NodeName) VALUES
((SELECT NodeId FROM Node WHERE NodeName = 'Root'), 'ChildA')
insert Node (ParentId, NodeName) VALUES
((SELECT NodeId FROM Node WHERE NodeName = 'Root'), 'ChildB')
insert Node (ParentId, NodeName) VALUES
((SELECT NodeId FROM Node WHERE NodeName = 'ChildA'), 'ChildA-A')
insert Node (ParentId, NodeName) VALUES
((SELECT NodeId FROM Node WHERE NodeName = 'ChildA-A'), 'ChildA-A-A')
获取Nodes
和子计数
;WITH
CountLevel AS
(
SELECT *, 1 AS Level FROM Node WHERE ParentId IS NULL
UNION ALL
SELECT child.*, parent.Level + 1
FROM Node child INNER JOIN CountLevel parent ON
child.ParentId = parent.NodeId
),
CountChild AS
(
SELECT NodeId, ParentId, 0 AS ChildCount
FROM Node leaf
WHERE NOT EXISTS(SELECT * FROM Node WHERE ParentId = leaf.NodeId)
UNION ALL
SELECT child.ParentId, (SELECT ParentId FROM Node WHERE NodeId = child.ParentId), child.ChildCount + 1
FROM CountChild child
WHERE child.ParentId IS NOT NULL
)
SELECT *, (SELECT SUM(ChildCount) FROM CountChild WHERE NodeId = CountLevel.NodeId) Child FROM CountLevel
结果
NodeId ParentId MaxChild NodeName Level Child
----------- ----------- ----------- -------------------- ----------- -----------
1 NULL -1 Root 1 4
2 1 -1 ChildA 2 2
3 1 -1 ChildB 2 0
4 2 -1 ChildA-A 3 1
5 4 -1 ChildA-A-A 4 0