在 SQL 用户定义函数中使用公用表表达式时出错
Posted
技术标签:
【中文标题】在 SQL 用户定义函数中使用公用表表达式时出错【英文标题】:Error using Common Table Expression in SQL User Defined Function 【发布时间】:2013-10-07 21:11:29 【问题描述】:CREATE FUNCTION [dbo].[udfGetNextEntityID]
()
RETURNS INT
AS
BEGIN
;WITH allIDs AS
(
SELECT entity_id FROM Entity
UNION SELECT entity_id FROM Reserved_Entity
)
RETURN (SELECT (MAX(entity_id) FROM allIDs )
END
GO
SQL 不是我的强项,但我无法弄清楚我在这里做错了什么。我希望该函数从 2 个表的联合中返回最大的 entity_id。运行脚本会报错:
Incorrect syntax near the keyword 'RETURN'.
我查看了在函数中使用 CTE 是否有一些限制,但找不到任何相关内容。我该如何纠正这个问题?
【问题讨论】:
【参考方案1】:CREATE FUNCTION [dbo].[udfGetNextEntityID]()
RETURNS INT
AS
BEGIN
DECLARE @result INT;
WITH allIDs AS
(
SELECT entity_id FROM Entity
UNION SELECT entity_id FROM Reserved_Entity
)
SELECT @result = MAX(entity_id) FROM allIDs;
RETURN @result;
END
GO
【讨论】:
【参考方案2】:你不能从函数中返回你正在做的事情。
利用局部变量并返回相同的变量。
CREATE FUNCTION [dbo].[udfGetNextEntityID]()
RETURNS INT
AS
BEGIN
DECLARE @MaxEntityId INT;
WITH allIDs AS
(
SELECT entity_id FROM Entity
UNION SELECT entity_id FROM Reserved_Entity
)
SELECT @MaxEntityId = MAX(entity_id) FROM allIDs;
RETURN @MaxEntityId ;
END
GO
【讨论】:
但是添加一个局部变量意味着它不再是一个内联函数 - 更慢。根本不是说你错了——只是在寻找 CTE 和内联 UDF 的优点。请参阅sqlservercentral.com/articles/T-SQL/91724 和***.com/questions/1084263/…【参考方案3】:虽然你可以做到,但你为什么需要 CTE?
RETURN
(
SELECT MAX(entity_id) FROM
(
SELECT entity_id FROM dbo.Entity
UNION ALL
SELECT entity_id FROM dbo.Reserved_Entity
) AS allIDs
);
也没有理由使用UNION
代替UNION ALL
,因为这几乎总是会引入昂贵的不同排序操作。还有please always use the schema prefix when creating / referencing any object。
【讨论】:
+1 同意。此外,对于 Union Vs Union All - 在这种情况下,您需要 Max 值并且不在乎行是否不同。所以,不要使用 UNION ,它会给出不同的行但会影响性能。请改用 Union All。 blog.sqlauthority.com/2009/03/11/… 谢谢@Ashish,但这不是我所说的吗? :-) 当然@Aaron。因为问这个问题的人说“SQL 不是我的强项”。所以,我想用 UNION Vs UNION ALL 的链接来补充你的答案,以供他参考。就是这样。【参考方案4】:create function tvfFormatstring (@string varchar(100))
returns @fn_table table
(id int identity(1,1),
item int)
as
begin
insert into @fn_table(item)
declare @result int
set @string = @string+'-'
;with cte (start,number)
as
(
select 1 as start , CHARINDEX('-',@string,1) as number
union all
select number+1 as start , CHARINDEX('-',@string,number+1) as number from cte
where number <= LEN(@string)
)
select @result = SUBSTRING(@string,start,number-start) from cte ;
return @result;
end
select * from tvfFormatstring ('12321-13542-15634')
【讨论】:
只提供代码不是正确答案。请详细说明。以上是关于在 SQL 用户定义函数中使用公用表表达式时出错的主要内容,如果未能解决你的问题,请参考以下文章
sqlserver 创建视图失败,原因:ORDER BY 子句在视图、内联函数、派生表、子查询和公用表表达式中无效