在SQL Server中,在表值函数中返回哪个选择语句/表?

时间:2017-04-14 14:37:40

标签: sql-server tsql sql-server-2012

我有一个表值函数没有一个返回变量(没有指定要返回的变量)。该表包含三个巨型CTE,后跟一个使用三个CTE以及一些其他表的select语句。

我只是想知道这个功能究竟在这里返回了什么?我知道显而易见的答案就是说SELECT * FROM DBO。[TEST_FUNCTION]。但我只是想知道 SQL Server如何决定返回的结果集?当以下面的方式定义函数时到底发生了什么?如果CTE具有相同的列名怎么办?返回哪个CTE?或者它是返回的最后一个select语句?如果在CTE之后有多个select语句怎么办?究竟是什么决定了函数返回的内容?非常感谢你

CREATE FUNCTION [dbo].[TEST_FUNCTION](@PARAMATER INT)
RETURNS TABLE AS
RETURN
WITH 
CTE 1 AS 
(SELECT STATEMENTS),
CTE 2 AS 
(SELECT STATEMENTS),
CTE 3 AS
(SELECT STATEMENTS)


--Separate from the above three CTEs code continues with another select statement
SELECT Columns, 
UNION CTE 2
INNER JOIN CTE 3, etc.

2 个答案:

答案 0 :(得分:1)

没有返回变量的TVP是内联表值函数。这些函数与视图非常相似,并在分析时扩展。查看查询计划 - 没有函数调用。 SQL服务器将其作为子查询处理。

  

内联函数可用于实现功能   参数化视图。

https://technet.microsoft.com/en-us/library/ms189294%28v=sql.105%29.aspx?f=255&MSPPError=-2147217396

答案 1 :(得分:1)

您正在创建一个内联表值函数,这意味着没有return语句。由于这种语法,你可以告诉它是内联的:RETURNS TABLE AS。 内联表值函数几乎与视图相同,除了它们: 1.可以接受参数 2.无法编入索引

您的示例中的CTE与子查询相同,除了一些超出您的问题范围的差异。

请注意,这两个查询返回的结果相同,并且处理方式相同:

WITH 
cte1 AS (SELECT v FROM (VALUES (1),(2)) t(v)),
cte2 AS (SELECT v FROM cte1),
cte3 AS (SELECT v FROM cte2)
SELECT * 
FROM cte3;

SELECT v
FROM
(
  SELECT v
  FROM
  (
    SELECT v
    FROM (SELECT v FROM (VALUES (1),(2)) t(v)) AS cte1
  ) AS cte2
) AS cte3;

CTE格式在嵌套时具有更清晰的语法,但与子查询示例一样,它只是一个查询。希望这是有道理的。

请注意此查询:

WITH 
CTE1 AS (SELECT 1   AS x),
CTE2 AS (SELECT 20  AS x),
CTE3 AS (SELECT 100 AS x);

--Separate from the above three CTEs code continues with another select statement
SELECT x AS x1, x*2 AS x2 
FROM CTE1
UNION ALL
SELECT CTE2.x, CTE3.x
FROM CTE2
INNER JOIN CTE3 ON CTE2.x <> CTE3.x;

返回此单个结果集:

x1          x2
----------- -----------
1           2
20          100

如果将它包装在内联表值函数中,它将返回相同的内容:

ALTER FUNCTION [dbo].[TEST_FUNCTION](@PARAMATER INT)
RETURNS TABLE AS
RETURN
WITH 
CTE1 AS (SELECT 1   AS x),
CTE2 AS (SELECT 20  AS x),
CTE3 AS (SELECT 100 AS x)


--Separate from the above three CTEs code continues with another select statement
SELECT x AS x1, x*2 AS x2 
FROM CTE1
UNION ALL
SELECT CTE2.x, CTE3.x
FROM CTE2
INNER JOIN CTE3 ON CTE2.x <> CTE3.x;
GO

SELECT * FROM dbo.TEST_FUNCTION(NULL);

此处函数返回与上面相同的内容。请注意,我没有对sample参数做任何事情。