当我们在SQL中使用用户定义的函数返回表时,我们为什么不使用BEGIN
和END
?
e.g。
CREATE FUNCTION Customers
(@minId int)
RETURNS TABLE
AS
RETURN(SELECT *
FROM TrackingItem ti
WHERE ti.Id >= @minId)
工作
但
CREATE FUNCTION Customers
(@minId int)
RETURNS TABLE
AS
BEGIN
RETURN(SELECT *
FROM TrackingItem ti
WHERE ti.Id >= @minId)
END
不起作用
答案 0 :(得分:1)
您没有标记DBMS,但是根据您的语法,我猜这是SQL Server ...
内嵌语法(不包含BEGIN...END
)的工作方式类似于带参数的VIEW
。在使用时,它将由查询优化器完全内联 - 就像代码是在使用函数的地方(几乎)编写的一样。这意味着:完全使用索引,统计数据,追逐结果......
但是 - 这在所有情况下都是不可能的(但在大多数情况下) - 你必须能够在一个语句中编写完整的逻辑。
第二个示例需要一个适合您想要返回的结果的表定义。您的代码必须对此虚拟表使用INSERT
,然后将其返回。您的示例中缺少这个。
如果可能的话,绝对应该避免这种方法。查询优化器将无法查看此代码以预测结果。它将无法以内联查询的方式使用临时/缓存结果或索引/统计信息。
答案 1 :(得分:0)
第一个,没有 BEGIN和END被称为“内联表值函数”。您只能在函数体内部使用单个语句来立即返回结果集。
第二个 BEGIN和END称为“多语句表值函数”。您可以在函数体内部有多个语句,然后在底部有一个RETURN语句来返回结果集。这允许您例如填充TABLE变量然后返回它。
内联表值函数可以被视为一个视图 - 在它扩展到调用查询中,基础表的统计信息可用于提供更好的执行计划。
多语句值函数不会像这样展开,并且在创建执行计划时不会从相同的好处中受益。
因此,最好避免使用多语句表值函数,而更喜欢内联函数,以获得这些好处并避免潜在的性能问题。
答案 2 :(得分:0)
您可以使用这种方式,返回表类型信息,您必须使用列定义表并通过表返回数据:尝试以下假设您有2列id和名称:
CREATE FUNCTION Customers(@minId INT)
RETURNS @@table TABLE (id INT, NAME VARCHAR(20))
AS
BEGIN
INSERT INTO @@table
SELECT id, name
FROM TrackingItem ti
WHERE ti.Id >= @minId
RETURN
END