我正在尝试创建一个标量函数来确定提供 ID 的用户或其任何下属是否在提供的订单 ID 集合下有订单。
注意我正在使用我自己的用户定义表类型IntegerIdTableType
来获取 OrderIds 的集合。
CREATE FUNCTION DoOrdersExistUnderUserOrUsersSubordinates
(
@orderIds dbo.IntegerIdTableType READONLY,
@userId INT
)
RETURNS BIT
AS
BEGIN
RETURN
(
WITH GetUserIds(ordinateUserId)
AS
(
SELECT ordinateUserId UserId
UNION ALL
SELECT GetUserIds(Subordinate.Id)
FROM UsersAccounts.Users Subordinates
WHERE Subordinates.SupervisorId = @ordinateUserId
)
SELECT CASE WHEN EXISTS
(
SELECT 1
FROM Orders
WHERE Orders.Id IN
(
SELECT Id
FROM @orderIds
)
AND Orders.UserId IN
(
SELECT UserId
FROM GetUserIds(@userId)
)
)
THEN CAST(1 AS BIT)
ELSE CAST(0 AS BIT)
END
)
END
这是我的Orders和Users表的一些示例数据。
用户
订单
预期成绩
DoOrdersExistUnderUserOrUsersSubordinates
使用以下值调用时,我期望得到以下结果。
我在使用此功能时遇到了 2 个问题:
语法错误:
关键字“WITH”附近的语法不正确。
')' 附近的语法不正确。
“GetUserIds”不是可识别的内置函数名称
即使没有包装在函数中,上述情况似乎也会发生。
我不知道将参数传递给递归 CTE 的正确方法是什么,但我已经看到 CTE 的声明在括号中有一个名称的示例,我认为它是一个参数
我尝试在分号之前立即放置一个分号,WITH
即使它是函数中唯一的语句,我只是在';'附近得到不正确的语法。而不是关键字“WITH”附近的语法不正确。
我也试过去掉BEGIN
and END
,这给了我在'RETURN'附近的不正确语法。, 加上关键字“with”附近的语法不正确。如果此语句是公用表表达式、xmlnamespaces
子句或更改跟踪上下文子句,则前面的语句必须以分号结束。如果我不包括多余的分号。
我该如何解决这一切?
当然,递归 CTE 必须能够接受一个参数,或者他们会递归什么?
更新:
在与Zohar_Peled 链接的文档的示例 F进行斗争之后,我最终发现参数并没有像这样传递到 CTE 中,而是加入到 CTE 中,然后通过其声明的括号保留在其中。然后在相应SELECT
的 s 中定义的任何内容都通过参数输出到称为 CTE 的任何内容(在这种情况下,外部SELECT Id FROM UserNodes
语句或 CTE 本身(用于递归))。
我将函数内的 SQL 语句更改为以下内容,它在函数外按预期工作。
WITH UserNodes([Root User ID], Id, SupervisorId)
AS
(
SELECT Users.Id, Users.Id, Users.SupervisorId
FROM UsersAccounts.Users
WHERE Users.SupervisorId IS NULL
UNION ALL
SELECT [Root User ID],
Users.Id,
Users.SupervisorId
FROM UsersAccounts.Users
JOIN UserNodes [Subordinate Descendant Users] ON [Subordinate Descendant Users].Id = Users.SupervisorId
)
SELECT CASE WHEN EXISTS
(
SELECT 1
FROM Orders
WHERE Orders.Id IN
(
SELECT Id
FROM @orderIds
)
AND Orders.UserId IN
(
SELECT Id
FROM UserNodes
WHERE [Root User ID] = @userId
)
)
THEN CAST(1 AS BIT)
ELSE CAST(0 AS BIT)
END
这单独工作很好(提供了所需的变量来替换缺少的函数参数),但是一旦我将它放回CREATE FUNCTION
块中,我就会面临与以前相同的语法错误(不包括 2.)。