通常來講,表表達式既不會對性能產生正面影響,也不會對性能產生負面影響。express
注意下面這種代碼風格:模塊化
SELECT orderyear, COUNT(DISTINCT custid) AS numcusts FROM (SELECT YEAR(orderdate), custid FROM Sales.Orders) AS D(orderyear, custid) GROUP BY orderyear;
公用表表達式(CTE,Common table expression)是用WITH子句定義的,通常格式爲:函數
WITH USACusts AS ( SELECT custid, companyname FROM Sales.Customers WHERE country = N'USA' ) SELECT * FROM USACusts;
和派生表同樣,一旦外部查詢完成,CTE的生命期就結束了。post
CTE分配列別名的方式——內聯格式和外部格式,內聯格式:性能
WITH C AS ( SELECT YEAR(orderdate) AS orderyear, custid FROM Sales.Orders ) SELECT orderyear, COUNT(DISTINCT custid) AS numcusts FROM C GROUP BY orderyear;
外部格式:ui
WITH C(orderyear, custid) AS ( SELECT YEAR(orderdate), custid FROM Sales.Orders ) SELECT orderyear, COUNT(DISTINCT custid) AS numcusts FROM C GROUP BY orderyear;
定義多個CTE:spa
WITH C1 AS ( SELECT YEAR(orderdate) AS orderyear, custid FROM Sales.Orders ), C2 AS ( SELECT orderyear, COUNT(DISTINCT custid) AS numcusts FROM C1 GROUP BY orderyear ) SELECT orderyear, numcusts FROM C2 WHERE numcusts > 70;
與嵌套的派生表代碼相比,上面這種模塊化的代碼大大提升了代碼的可讀性和可維護性。code
建立一個視圖:blog
USE TSQLFundamentals2008; IF OBJECT_ID('Sales.USACusts') IS NOT NULL DROP VIEW Sales.USACusts; GO CREATE VIEW Sales.USACusts AS SELECT custid, companyname, contactname, contacttitle, address, city, region, postalcode, country, phone, fax FROM Sales.Customers WHERE country = N'USA'; GO
記住一點,在定義表表達式的查詢語句中不容許出現ORDER BY子句,由於關係表之間的行沒有順序。試圖建立一個有序視圖也是不合理的,SQL Server將會報錯。應該在使用視圖的外部查詢中使用ORDER BY子句。ip
如下代碼建立一個內聯表值函數:
USE TSQLFundamentals2008; IF OBJECT_ID('dbo.fn_GetCustOrders') IS NOT NULL DROP FUNCTION dbo.fn_GetCustOrders; GO CREATE FUNCTION dbo.fn_GetCustOrders (@cid AS INT) RETURNS TABLE AS RETURN SELECT orderid, custid, empid, orderdate, requireddate, shippeddate, shipperid, freight, shipname, shipaddress, shipcity, shipregion, shippostalcode, shipcountry FROM Sales.Orders WHERE custid = @cid; GO
使用這個函數:
SELECT orderid, custid FROM dbo.fn_GetCustOrders(1) AS CO;
藉助表表達式能夠簡化代碼,提升代碼的維護性,還能夠封裝查詢邏輯。當須要使用表表達式時,若是是不計劃重用它們的定義,則使用派生表或者CTE;當須要定義可重用的表表達式時,能夠使用視圖和內聯表值函數。