2012-06-28 61 views
4

我有一些問題試圖從SQL函數中返回一個表,其中創建表的SQL是動態編寫的。編寫動態SQL函數

到目前爲止,我有:

CREATE FUNCTION dbo.SEL_PCD 
(
    @COBDate AS DATETIME, 
    @FileName AS VARCHAR(50), 
    @PC AS VARCHAR(50), 
    @MyList AS VARCHAR(max), 

    DECLARE @SQL VARCHAR(max) 

    SET @SQL = 'SELECT * FROM 
        (SELECT tab1.TID FROM 
         (SELECT TID FROM dbo.SEL_RT('[email protected]+','[email protected]+') WHERE BID IN ('+ @MyList +')) tab1 
        JOIN 
         (SELECT TID FROM CT WHERE (Col_Name LIKE %' + @PC + '% OR Bk LIKE %' + @PC + '%) AND FileName = ' + @FileName + ' AND COBDate = @COBDate) tab2 
        ON tab1.TID = tab2.TID) tab3 
       JOIN 
        (SELECT TID, Value FROM CR WHERE BID IN (' + @MyList + ') AND COBDate = ' + @COBDate + ' AND FileName = ' + @FileName + 'AND ScenID = 266) tab7 
       ON tab3.TID = tab7.TID' 

) 
RETURNS TABLE AS 
RETURN 
(
    EXEC sp_executesql @SQL 
) 
GO 

我收到錯誤聲明SQL變量。我可以通過執行命令返回表嗎?

回答

3

有這一個嘗試:

CREATE PROCEDURE dbo.SEL_PCD 
(
    @COBDate DATETIME, 
    @FileName VARCHAR(50), 
    @PC VARCHAR(50), 
    @MyList VARCHAR(max) 
) AS 

    DECLARE @SQL VARCHAR(max) 

    SELECT @SQL = 'SELECT * FROM 
        (SELECT tab1.TID FROM 
         (SELECT TID FROM dbo.SEL_RT('[email protected]+','[email protected]+') WHERE BID IN ('+ @MyList +')) tab1 
        JOIN 
         (SELECT TID FROM CT WHERE (Col_Name LIKE %' + @PC + '% OR Bk LIKE %' + @PC + '%) AND FileName = ' + @FileName + ' AND COBDate = @COBDate) tab2 
        ON tab1.TID = tab2.TID) tab3 
       JOIN 
        (SELECT TID, Value FROM CR WHERE BID IN (' + @MyList + ') AND COBDate = ' + @COBDate + ' AND FileName = ' + @FileName + 'AND ScenID = 266) tab7 
       ON tab3.TID = tab7.TID' 

EXEC(@SQL) 

功能

  • 可以用SELECT語句中
  • 沒有返回輸出參數,但返回表變量
  • 你可以加入UDF
  • 不能用於更改服務器配置
  • 不能成爲第
  • XML所用
  • 不能函數內有交易

存儲過程

  • 已經使用EXEC或EXECUTE
  • 返回輸出參數
  • 可以創建表,但不會返回表變量
  • 你不能加入SP
  • 可以用來改變服務器的配置
  • 可以用FOR XML子句中使用
  • 可以SP內有交易
+0

函數和存儲過程之間的區別來源:http://www.sqlservercentral.com/Forums/Topic416974-8-1.aspx我承認,我很懶惰 – fancyPants

3

不能從函數內調用存儲過程,包括存儲過程EXECUTESP_EXECUTESQL。這意味着你不能在一個函數中嵌入動態sql。


你不能調用存儲過程的原因是因爲功能不允許有副作用(調用它們本身不能改變任何數據 - 他們不能插入,更新或刪除)。但是存儲過程可以。這意味着調用存儲過程的函數會突然變得有副作用。

SP's可以調用函數,而不是相反。


此外,SQL編譯成執行計劃。那時候,正在使用的表和索引都是固定的。如果一個函數包含可能的動態sql;要使用的表等在編譯時並不知道,而SQL沒有這種能力。


在你的情況你查詢的唯一部分似乎需要動態SQL是要傳遞一個逗號分隔的列表作爲@myList參數。但是,還有一種替代方法。

查找在線(和SO上的許多)可用的許多dbo.fn_split()函數之一。然後使用該函數來加入數據...

CREATE FUNCTION dbo.SEL_PCD(@COBDate  AS DATETIME, 
          @FileName AS VARCHAR(50), 
          @PC   AS VARCHAR(50), 
          @MyList  AS VARCHAR(max) 
          ) 
RETURNS TABLE 
AS 
RETURN 
    SELECT 
    CR.TID, 
    CR.Value 
    FROM 
    dbo.SEL_RT(@COBDate, @FileName) AS RT 
    INNER JOIN 
    CT 
    ON CT.TID = RT.TID 
    INNER JOIN 
    CR 
    ON CR.TID = RT.TID 
    WHERE 
    (CT.Col_Name LIKE '%'[email protected]+'%' OR CT.Bk LIKE '%'[email protected]+'%') 
    AND CT.FileName = @FileName 
    AND CT.COBDate = @COBDate 
    AND CR.FileName = @FileName 
    AND CR.COBDate = @COBDate 
    AND CR.ScenID = 266 
    AND RT.BID IN (SELECT id FROM dbo.fn_split(@myList, ',') AS my_list) 
    AND CR.BID IN (SELECT id FROM dbo.fn_split(@myList, ',') AS my_list) 
0

不能使用在功能上執行命令

CREATE PROCEDURE dbo.SEL_PCD4 
(
    @COBDate AS DATETIME, 
    @FileName AS VARCHAR(50), 
    @PC AS VARCHAR(50), 
    @MyList AS VARCHAR(max) 
) AS 
    DECLARE @SQL VARCHAR(max) 

    SET @SQL = 'SELECT * FROM 
        (SELECT tab1.TID FROM 
         (SELECT TID FROM dbo.SEL_RT('[email protected]+','[email protected]+') WHERE BID IN ('+ @MyList +')) tab1 
        JOIN 
         (SELECT TID FROM CT WHERE (Col_Name LIKE %' + @PC + '% OR Bk LIKE %' + @PC + '%) AND FileName = ' + @FileName + ' AND COBDate = @COBDate) tab2 
        ON tab1.TID = tab2.TID) tab3 
       JOIN 
        (SELECT TID, Value FROM CR WHERE BID IN (' + @MyList + ') AND COBDate = ' + @COBDate + ' AND FileName = ' + @FileName + 'AND ScenID = 266) tab7 
       ON tab3.TID = tab7.TID' 

    EXEC sp_executesql @SQL 

GO