【问题标题】:SQL Server: From a view, calling a function with a table-valued parameterSQL Server:从视图中,调用带有表值参数的函数
【发布时间】:2015-08-26 15:17:07
【问题描述】:

在 SQL Server 中,如果我有一个采用表值参数参数的标量值函数,定义如下(简化示例):

CREATE TYPE IntTableType AS TABLE(Value INT); 

CREATE FUNCTION dbo.MeetsCustomRequirements
(
    @TypeIDs IntTableType READONLY
)
RETURNS TINYINT AS 
BEGIN
    -- (Function logic here; returns either 0 or 1 based on the specified @TypeIDs values)
END

我希望能够从视图中调用该函数,其中视图的表值参数是从内联查询生成的,例如:

CREATE VIEW dbo.vEligibleItems AS 
    SELECT i.ItemID
    FROM tItems i
    WHERE dbo.MeetsCustomRequirements (
        (SELECT TypeID FROM tItemTypes WHERE ItemID = i.ItemID)
    );

但是,这不起作用,因为该嵌套 SELECT 查询的结果不是IntTableType(尽管它INT 值的列表)。 (生成的具体错误为Error 206: Operand type clash: int is incompatible with IntTableType。)

我的两部分问题:有没有办法调用从视图中获取表值参数参数的函数?如果不是,有哪些替代方法可以完成同样的事情?

数据库是 SQL Server 2008。

(将函数中的逻辑内联到视图中并不理想,因为函数是从几个不同的地方调用的,而不仅仅是从这个视图中。)

【问题讨论】:

  • 也许你需要交叉申请
  • 你能把标量函数改成内联表值函数吗?请注意,这意味着单个选择语句。如果您有多个语句,这将无济于事,实际上性能可能会更差。那么交叉应用是一种更好的方法。仔细看看你的 where 谓词。你有一个标量函数,但你试图传递一整列,你也需要一些条件。
  • 是的,直接在 tItems 和 tItemTypes 之间进行内部连接似乎更好。 dbo.MeetsCustomRequirements中的逻辑是什么?
  • 在我的真实代码中,标量值函数还需要几个其他参数。该逻辑本质上是一个带有多个 WHEN 子句的大型 CASE 语句,这些子句查看输入参数值并针对各种组合返回 1,如果没有命中任何组合则返回 0。
  • CASE 块是只检查表值参数中的一行还是所有行?

标签: sql sql-server table-valued-parameters


【解决方案1】:

我认为VIEW 不可能

创建视图 [模式名称。 ] view_name [ (column [ ,...n ] ) ]

[ 与 [ ,...n ] ]

AS select_statement

[带有检查选项]

[; ]

使用视图语法,您可以获得的最大值是 CTE。要传递 TVP 参数,您需要在某处声明它,但不能在视图定义中进行。

非常丑陋的解决方案只是概念而不是实际代码(使用 XML 将多个值传递给辅助函数):

CREATE VIEW dbo.vEligibleItems
AS
WITH cte (view.*, XML_with_all_types_id) AS
(
    SELECT *,
       [XML_with_all_types_id] = magic_here(
            SELECT iTypeID FROM tItemTypes t WHERE WHERE t.ItemID = i.ItemID)
    FROM tItems i      
)
SELECT *
FROM cte
WHERE dbo.MeetsCustomRequirements_helper(XML_with_all_types_id) = 1

CREATE FUNCTION dbo.MeetsCustomRequirements_helper(@xml XML)
RETURNS INT
AS
(
   // unwrap xml to TVP
   DECLARE @tvp your_tvp_type;
   INSERT INTO @tvp(cols)
   SELECT *
   FROM @xml.node(...);

   DECLARE @result = dbo.MeetsCustomRequirements(@tvp);

   RETURN @result
)

您能否将您的视图更改为表值用户定义函数并在需要时用视图覆盖它(我知道性能会很差):

CREATE VIEW name
AS
SELECT *
FROM dbo.fn_getdata();

CREATE FUNCTION dbo.fn_getdata()
RETURNS @result TABLE
AS 
BEGIN

  /* multi-statement you can declare your TVP */

END

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-01-26
    • 2020-02-13
    • 1970-01-01
    • 2011-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多