2015-08-26 147 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