表表达式是一个命名的查询表达式,返回一个虚拟表。
一. 视图(View)
视图是由单个的 SELECT 查询语句定义的。视图中不可以有 ORDER BY 子句和 TOP 、OFFSET 等。
视图也是一种表表达式,与前面几种类型的表表达式相比,视图的特点是预先定义并存储在数据库中。
视图类似于导出的表和CTE,使用了视图的查询可以封装并且更简单。
CREATE VIEW EmpPhoneList AS SELECT empid, lastname, firstname, phone FROM Employees |
二、TVF(Table-valued function,表值函数)
用户可以自定义一个TVF,此函数将返回 table 数据类型(虚拟表)。
SQL Server 提供两种类型的TVF:
(1)内联(Inline)TVF
对于内联表值函数,没有函数主体;表是单个 SELECT 语句的结果集。
下面的示例将创建一个内联TVF。 对于销售给商店的每个产品,该函数返回三列,分别为 ProductID、Name 以及各个商店年初至今总数的累计 YTD Total 。
CREATE FUNCTION Sales.ufn_SalesByStore (@storeid int) RETURNS TABLE AS RETURN ( SELECT P.ProductID, P.Name, SUM(SD.LineTotal) AS 'Total' FROM Production.Product AS P JOIN Sales.SalesOrderDetail AS SD ON SD.ProductID = P.ProductID JOIN Sales.SalesOrderHeader AS SH ON SH.SalesOrderID = SD.SalesOrderID JOIN Sales.Customer AS C ON SH.CustomerID = C.CustomerID WHERE C.StoreID = @storeid GROUP BY P.ProductID, P.Name ); |
若要调用该函数,请运行此查询。
SELECT * FROM Sales.ufn_SalesByStore (602); |
(2)多语句(Multi-statement)TVF
对于多语句表值函数,在 BEGIN...END 语句块中定义的函数体包含一系列 T-SQL 语句,这些语句可生成行并将其插入将返回的表中。
视图本身是不可以使用参数的,而表值函数可以看作是一个参数化的视图。
三、派生表(Derived table)
派生表也称为子查询表或内联视图,是在外部查询的 FROM 子句中定义的。
派生表只存在于外部查询。一旦外部查询完成后,派生表就消失了。
下例是两个嵌套的派表。
SELECT orderyear, cust_count FROM (SELECT orderyear, COUNT(DISTINCT custid) AS cust_count FROM ( SELECT YEAR(orderdate) AS orderyear ,custid FROM Orders) AS derived_table_1 GROUP BY orderyear) AS derived_table_2 WHERE cust_count > 80; |
四、CTE(Common Table Expression,公用表表达式)
CTE作为一个表表达式,在一个查询中被定义,而且能被紧随其后的首个查询语句(在同一个批处理中)多次引用。
以下例子将创建一个多语句VTF,并在函数中使用CTE:
CREATE FUNCTION dbo.ufn_FindReports (@InEmpID INTEGER) RETURNS @retFindReports TABLE ( EmployeeID int primary key NOT NULL, FirstName nvarchar(255) NOT NULL, LastName nvarchar(255) NOT NULL, JobTitle nvarchar(50) NOT NULL, RecursionLevel int NOT NULL ) --Returns a result set that lists all the employees who report to the --specific employee directly or indirectly.*/ AS BEGIN WITH EMP_cte(EmployeeID, OrganizationNode, FirstName, LastName, JobTitle, RecursionLevel) -- CTE name and columns AS ( SELECT e.BusinessEntityID, e.OrganizationNode, p.FirstName, p.LastName, e.JobTitle, 0 -- Get the initial list of Employees for Manager n FROM HumanResources.Employee e INNER JOIN Person.Person p ON p.BusinessEntityID = e.BusinessEntityID WHERE e.BusinessEntityID = @InEmpID UNION ALL SELECT e.BusinessEntityID, e.OrganizationNode, p.FirstName, p.LastName, e.JobTitle, RecursionLevel + 1 -- Join recursive member to anchor FROM HumanResources.Employee e INNER JOIN EMP_cte ON e.OrganizationNode.GetAncestor(1) = EMP_cte.OrganizationNode INNER JOIN Person.Person p ON p.BusinessEntityID = e.BusinessEntityID ) -- copy the required columns to the result of the function INSERT @retFindReports SELECT EmployeeID, FirstName, LastName, JobTitle, RecursionLevel FROM EMP_cte RETURN END; |
示例创建了一个表值函数。此函数具有一个输入参数 EmployeeID 而返回直接或间接向指定员工报告的所有员工的列表。下面的示例调用此函数。
SELECT EmployeeID, FirstName, LastName, JobTitle, RecursionLevel FROM dbo.ufn_FindReports(1); |
关于视图、派生表和CTE,可以参考