📜  SQL 中的 CTE

📅  最后修改于: 2021-09-09 10:18:00             🧑  作者: Mango

公共表表达式 (CTE)被引入标准 SQL 以简化派生表不适合的各种 SQL 查询类。 CTE 是在 SQL Server 2005 中引入的,公用表表达式 (CTE) 是一个临时命名的结果集,您可以在 SELECT、INSERT、UPDATE 或 DELETE 语句中引用它。您还可以在 CREATE a 视图中使用 CTE,作为视图的 SELECT 查询的一部分。此外,从 SQL Server 2008 开始,您可以向新的 MERGE 语句添加 CTE。

使用 CTE –
我们可以通过在 SELECT、INSERT、UPDATE、DELETE 或 MERGE 语句之前直接添加 WITH 子句来定义 CTE。 WITH 子句可以包含一个或多个用逗号分隔的 CTE。可以遵循以下语法:

[WITH  [, ...]]  
 
::=
cte_name [(column_name [, ...])]
AS (cte_query) 

使用 CTE 定义 WITH 子句后,您可以像引用任何其他表一样引用 CTE。但是,您只能在紧随 WITH 子句的语句的执行范围内引用 CTE。运行语句后,CTE 结果集不可用于其他语句。

创建递归公用表表达式 –
递归 CTE 是在该 CTE 中引用自身的 CTE。递归 CTE 在处理分层数据时很有用,因为 CTE 会继续执行,直到查询返回整个层次结构。

分层数据的典型示例是包含员工列表的表。对于每个员工,该表提供了对该人的经理的引用。该引用本身就是同一表中的员工 ID。您可以使用递归 CTE 来显示员工数据的层次结构。

如果 CTE 被错误地创建,它会进入无限循环。为了防止这种情况,可以在主 SELECT、INSERT、UPDATE、DELETE 或 MERGE 语句的 OPTION 子句中添加 MAXRECURSION 提示。

创建一个表:

CREATE TABLE Employees
(
  EmployeeID int NOT NULL PRIMARY KEY,
  FirstName varchar(50) NOT NULL,
  LastName varchar(50) NOT NULL,
  ManagerID int NULL
)

INSERT INTO Employees VALUES (1, 'Ken', 'Thompson', NULL)
INSERT INTO Employees VALUES (2, 'Terri', 'Ryan', 1)
INSERT INTO Employees VALUES (3, 'Robert', 'Durello', 1)
INSERT INTO Employees VALUES (4, 'Rob', 'Bailey', 2)
INSERT INTO Employees VALUES (5, 'Kent', 'Erickson', 2)
INSERT INTO Employees VALUES (6, 'Bill', 'Goldberg', 3)
INSERT INTO Employees VALUES (7, 'Ryan', 'Miller', 3)
INSERT INTO Employees VALUES (8, 'Dane', 'Mark', 5)
INSERT INTO Employees VALUES (9, 'Charles', 'Matthew', 6)
INSERT INTO Employees VALUES (10, 'Michael', 'Jhonson', 6) 

在创建Employees 表后,创建以下SELECT 语句,该语句前面是一个包含名为cteReports 的CTE 的WITH 子句:

WITH
  cteReports (EmpID, FirstName, LastName, MgrID, EmpLevel)
  AS
  (
    SELECT EmployeeID, FirstName, LastName, ManagerID, 1
    FROM Employees
    WHERE ManagerID IS NULL
    UNION ALL
    SELECT e.EmployeeID, e.FirstName, e.LastName, e.ManagerID, 
      r.EmpLevel + 1
    FROM Employees e
      INNER JOIN cteReports r
        ON e.ManagerID = r.EmpID
  )
SELECT
  FirstName + ' ' + LastName AS FullName, 
  EmpLevel,
  (SELECT FirstName + ' ' + LastName FROM Employees 
    WHERE EmployeeID = cteReports.MgrID) AS Manager
FROM cteReports 
ORDER BY EmpLevel, MgrID 

因此,当您需要生成可在 SELECT、INSERT、UPDATE、DELETE 或 MERGE 语句中访问的临时结果集时,CTE 可能是一个有用的工具。