如何将从函数返回的用户定义 table 类型作为参数传递给另一个内联函数(没有 'DECLARE')?
How to pass a user defined table type returned from a function as a parameter to another inline function (without 'DECLARE')?
恐怕答案是“不,你不能”,但由于我在任何地方都找不到这个解释,所以我还是要问一下。
给定用户定义的 table 类型:
CREATE TYPE MyType AS TABLE(
[Id] UNIQUEIDENTIFIER NOT NULL,
[Name] NVARCHAR(200) NOT NULL
)
还有一个 return 类型的函数:
CREATE FUNCTION [dbo].[fnFind]
(
@info UNIQUEIDENTIFIER
)
RETURNS TABLE AS
RETURN( SELECT TOP 1 Id, Name FROM TblUsers WHERE Id = @info );
另一个接受该类型的函数:
CREATE FUNCTION [dbo].[fnName]
(
@single MyType READONLY
)
RETURNS TABLE AS
RETURN( SELECT TOP 1 Name, 42 AS NextColumn, 43 AS MoreCols FROM @single );
由于 fnFind
的 return 值符合 fnName
接受的值,我希望我可以做类似的事情:
SELECT * FROM SomeOtherTable sot
INNER JOIN dbo.fnName(dbo.fnFind(sot.Id)) f ON sot.Id = f.Id
-- OR using the select-syntax, since it is a table
SELECT * FROM SomeOtherTable sot
INNER JOIN dbo.fnName((SELECT * FROM dbo.fnFind(sot.Id))) f ON sot.Id = f.Id
不幸的是,该语法会导致错误。可能,如果我将它添加到一个多语句脚本或函数中,我可以只分配它并传递它,但是如果我想在 TVF 行中使用这样的构造,我相信我不能使用 DECLARE
语句.所以我希望有一些语法可以做到这一点。
(抱歉上面的函数很简单,只是为了说明问题。目前使用在一个触发器中,所以我可以使用多个语句,但我想在里面使用这个SELECT
语句,这将需要这种“功能管道”)
更新: 这就是我想要实现的目标。我知道我可以通过使用游标或其他一些魔法来做到这一点,但由于逻辑 table inserted
有一个或多个行,我不能简单地声明一个变量:
此处 fnGetMatchingKey
接受一个 UDTT,fnGetSearchFields
return 一个 table 与该 UDTT 具有相同的架构,但这种语法似乎是不允许的:
UPDATE TableX
SET MatchingKeyId = (SELECT TOP 1 KeyId FROM dbo.fnGetMatchingKey(wi.Id, [dbo].[fnGetSearchFields](wi.Id)))
FROM WorkItems wi
INNER JOIN inserted i
ON wi.Id= i.Id
对于 select
,我想你正在寻找 apply
:
SELECT *
FROM SomeOtherTable sot CROSS APPLY
dbo.fnName(dbo.fnFind(sot.Id)) f
我不确定您是否需要条件 sot.Id = f.Id
。我猜这是多余的。
恐怕答案是“不,你不能”,但由于我在任何地方都找不到这个解释,所以我还是要问一下。
给定用户定义的 table 类型:
CREATE TYPE MyType AS TABLE(
[Id] UNIQUEIDENTIFIER NOT NULL,
[Name] NVARCHAR(200) NOT NULL
)
还有一个 return 类型的函数:
CREATE FUNCTION [dbo].[fnFind]
(
@info UNIQUEIDENTIFIER
)
RETURNS TABLE AS
RETURN( SELECT TOP 1 Id, Name FROM TblUsers WHERE Id = @info );
另一个接受该类型的函数:
CREATE FUNCTION [dbo].[fnName]
(
@single MyType READONLY
)
RETURNS TABLE AS
RETURN( SELECT TOP 1 Name, 42 AS NextColumn, 43 AS MoreCols FROM @single );
由于 fnFind
的 return 值符合 fnName
接受的值,我希望我可以做类似的事情:
SELECT * FROM SomeOtherTable sot
INNER JOIN dbo.fnName(dbo.fnFind(sot.Id)) f ON sot.Id = f.Id
-- OR using the select-syntax, since it is a table
SELECT * FROM SomeOtherTable sot
INNER JOIN dbo.fnName((SELECT * FROM dbo.fnFind(sot.Id))) f ON sot.Id = f.Id
不幸的是,该语法会导致错误。可能,如果我将它添加到一个多语句脚本或函数中,我可以只分配它并传递它,但是如果我想在 TVF 行中使用这样的构造,我相信我不能使用 DECLARE
语句.所以我希望有一些语法可以做到这一点。
(抱歉上面的函数很简单,只是为了说明问题。目前使用在一个触发器中,所以我可以使用多个语句,但我想在里面使用这个SELECT
语句,这将需要这种“功能管道”)
更新: 这就是我想要实现的目标。我知道我可以通过使用游标或其他一些魔法来做到这一点,但由于逻辑 table inserted
有一个或多个行,我不能简单地声明一个变量:
此处 fnGetMatchingKey
接受一个 UDTT,fnGetSearchFields
return 一个 table 与该 UDTT 具有相同的架构,但这种语法似乎是不允许的:
UPDATE TableX
SET MatchingKeyId = (SELECT TOP 1 KeyId FROM dbo.fnGetMatchingKey(wi.Id, [dbo].[fnGetSearchFields](wi.Id)))
FROM WorkItems wi
INNER JOIN inserted i
ON wi.Id= i.Id
对于 select
,我想你正在寻找 apply
:
SELECT *
FROM SomeOtherTable sot CROSS APPLY
dbo.fnName(dbo.fnFind(sot.Id)) f
我不确定您是否需要条件 sot.Id = f.Id
。我猜这是多余的。