1. SQL Server递归子节点查询
1.1 什么是递归子节点查询
递归子节点查询,顾名思义,指的是在树形结构数据表中,通过某一个节点对其子节点的查询,或者对其父节点的查询。
比如,在一个员工表中,我们有各个部门的员工,每个员工有一个上级领导,那么我们就可以使用递归查询,通过一个员工ID查询其所有的下属员工,或者通过一个员工ID查询其所有的上级领导。
1.2 递归查询的实现
在SQL Server中,递归查询的实现需要使用到Common Table Expression(CTE)。
CTE是一种临时的命名查询,可以在其他SQL语句中被引用。CTE可以通过WITH关键字定义,然后再SELECT、INSERT、UPDATE、DELETE、MERGE或者CREATE VIEW语句中使用。
1.3 递归查询的语法
WITH CTEName (ColumnList) AS
(
-- Anchor Member (non-recursive term)
SELECT ColumnList FROM TableName WHERE ...
UNION ALL
-- Recursive Member Definition
SELECT ColumnList FROM TableName t
JOIN CTEName c ON ... WHERE ...
) SELECT ColumnList FROM CTEName
上述语法中,Anchor Member是递归查询的起点,也就是第一次查询,查询结果将被使用在Recursive Member Definition中。
Recursive Member Definition中必须包含JOIN操作,使得递归查询能够在每次迭代中连接到更多的数据行。
最后的SELECT语句将返回所有的递归查询结果。
1.4 递归子节点查询实例
以下是一个演示如何使用递归查询,查询某个员工ID的所有下属员工的例子。
-- 创建Employee表,并向其中插入数据
CREATE TABLE Employee
(
EmployeeID INT PRIMARY KEY,
EmployeeName NVARCHAR(50),
SupervisorID INT
);
INSERT INTO Employee VALUES (1, 'John', NULL);
INSERT INTO Employee VALUES (2, 'Mike', 1);
INSERT INTO Employee VALUES (3, 'Alice', 1);
INSERT INTO Employee VALUES (4, 'Tom', 2);
INSERT INTO Employee VALUES (5, 'Jack', 2);
INSERT INTO Employee VALUES (6, 'Eric', 3);
-- 查询EmployeeID为2的员工的所有下属员工
WITH Subordinates
AS
(
SELECT EmployeeID, EmployeeName, SupervisorID, 0 as Level
FROM Employee
WHERE EmployeeID = 2
UNION ALL
SELECT e.EmployeeID, e.EmployeeName, e.SupervisorID, s.Level + 1
FROM Employee e
JOIN Subordinates s ON s.EmployeeID = e.SupervisorID
)
SELECT * FROM Subordinates
以上查询语句中,首先使用了一个Anchor Member,查询EmployeeID为2的员工。
然后在Recursive Member Definition中,使用了 JOIN 操作连接到更多的数据行,查询的结果将使用 UNION ALL 操作连接返回。
最后,使用 SELECT 语句返回递归查询的结果。
1.5 递归父节点查询实例
以下是一个演示如何使用递归查询,查询某个员工ID的所有上级领导的例子。
WITH Supervisors
AS
(
SELECT EmployeeID, EmployeeName, SupervisorID, 0 as Level
FROM Employee
WHERE EmployeeID = 6
UNION ALL
SELECT e.EmployeeID, e.EmployeeName, e.SupervisorID, s.Level + 1
FROM Employee e
JOIN Supervisors s ON s.SupervisorID = e.EmployeeID
)
SELECT EmployeeID, EmployeeName, SupervisorID, Level FROM Supervisors
以上查询语句中,首先使用了一个Anchor Member,查询EmployeeID为6的员工。
然后在Recursive Member Definition中,使用了 JOIN 操作连接到更多的数据行,查询的结果将使用 UNION ALL 操作连接返回。
最后,使用 SELECT 语句返回递归查询的结果。
2. SQL查询表结构
2.1 查询表结构的语法
在SQL Server中,查询表结构需要使用到系统表sysobjects、syscolumns和sysindexes。
sysobjects表中包含了数据库中的各种对象,包括表、视图、存储过程等。
syscolumns表中包含了表的列信息,包括列名、数据类型、长度等。
sysindexes表中包含了表的索引信息。
查询表结构的SQL语法如下所示:
SELECT
object_name(c.object_id) AS TableName,
c.name AS ColumnName,
t.name AS DataType,
c.max_length AS Length,
i.name AS IndexName,
i.type AS IndexType,
i.is_unique AS IsUnique,
i.is_primary_key AS IsPrimaryKey,
i.fill_factor AS FillFactor,
i.is_padded AS IsPadded,
i.allow_row_locks AS AllowRowLocks,
i.allow_page_locks AS AllowPageLocks
FROM sys.objects o
INNER JOIN sys.columns c ON o.object_id = c.object_id
INNER JOIN sys.types t ON c.system_type_id = t.system_type_id
LEFT OUTER JOIN sys.index_columns ic ON c.object_id = ic.object_id AND c.column_id = ic.column_id
LEFT OUTER JOIN sys.indexes i ON ic.object_id = i.object_id AND ic.index_id = i.index_id
WHERE o.type = 'U' AND o.name = 'TableName'
ORDER BY c.column_id
2.2 查询表结构实例
以下是一个演示如何使用SQL查询某个表的结构的例子。
SELECT
object_name(c.object_id) AS TableName,
c.name AS ColumnName,
t.name AS DataType,
c.max_length AS Length,
i.name AS IndexName,
i.type AS IndexType,
i.is_unique AS IsUnique,
i.is_primary_key AS IsPrimaryKey,
i.fill_factor AS FillFactor,
i.is_padded AS IsPadded,
i.allow_row_locks AS AllowRowLocks,
i.allow_page_locks AS AllowPageLocks
FROM sys.objects o
INNER JOIN sys.columns c ON o.object_id = c.object_id
INNER JOIN sys.types t ON c.system_type_id = t.system_type_id
LEFT OUTER JOIN sys.index_columns ic ON c.object_id = ic.object_id AND c.column_id = ic.column_id
LEFT OUTER JOIN sys.indexes i ON ic.object_id = i.object_id AND ic.index_id = i.index_id
WHERE o.type = 'U' AND o.name = 'Employee'
ORDER BY c.column_id
以上查询语句中,使用了系统表sys.objects、sys.columns和sys.types,查询Employee表中的所有列信息和索引信息。
结论
本文介绍了在SQL Server中,如何使用递归子节点查询来查询树形结构数据表中的子节点和父节点;以及如何使用系统表来查询某个表的结构信息。