2015-08-26 118 views
1

在SQL Server中,如果我有一个采用表值参数参数的标量值函数,其定义如下(简化示例):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) 
    ); 

然而,这并未” t工作,因为嵌套SELECT查询的结果不是IntTableType(即使它是值的列表INT值)。 (生成的具体错误是Error 206: Operand type clash: int is incompatible with IntTableType。)

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

数据库是SQL Server 2008的

(瞻逻辑视图中的函数内联并不理想,因为该功能是由几个不同的地方,而不是仅仅从这一说法叫。)

+1

也许你需要CROSS APPLY – lad2025

+0

您可以更改标量函数为内嵌表值函数?请注意,这意味着一个选择语句。如果你有多个陈述,这不会有帮助,实际上表现可能会更糟。那么交叉应用是一种更好的方法。仔细看看你那里的谓词。你有一个标量函数,但是你试图把它传递给一个整列,你也需要一些条件。 –

+0

是的,这似乎更好地直接在tItems和tItemTypes之间进行内部连接。 'dbo.MeetsCustomRequirements'中有什么样的逻辑? – ps2goat

回答

1

我认为这是不可能的VIEW

CREATE VIEW [schema_name。 ] VIEW_NAME [(列[,... n])的]

[WITH [,... n]的]

AS select_statement中

[WITH CHECK OPTION]

[; ]

最大可以获得的视图语法是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