4

テーブルを作成するための 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('+@COBDate+','+@FileName+') 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 変数の宣言でエラーが発生します。execute コマンドを使用してテーブルを返してもよろしいですか?

4

3 に答える 3

3

EXECUTEストアドプロシージャまたはを含む関数内からストアドプロシージャを呼び出すことはできませんSP_EXECUTESQL。これは、動的SQLを関数内に埋め込むことができないことを意味します。


ストアドプロシージャを呼び出せない理由は、関数に副作用がないためです(関数を呼び出すと、それ自体でデータを変更することはできません。挿入、更新、削除することはできません)。しかし、ストアドプロシージャは可能です。これは、ストアドプロシージャを呼び出す関数が、突然副作用を起こす可能性があることを意味します。

SPは関数を呼び出すことができますが、その逆はできません。


また、SQLは実行プランにコンパイルされます。その時点で、使用されているテーブルとインデックスはすべて固定されます。関数に動的SQLが含まれている場合、それは可能です。使用されるテーブルなどはコンパイル時に不明であり、SQLにはその機能がありません。


あなたの場合、動的SQLを必要としていると思われるクエリの唯一の部分は、@myListパラメーターとしてコンマ区切りのリストを渡すことです。ただし、別のアプローチがあります。

dbo.fn_split()オンラインで利用できる多くの機能の1つ(およびSOで利用できる多くの機能)を探してください。次に、その関数を使用してデータを結合します...

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 '%'+@PC+'%' OR CT.Bk LIKE '%'+@PC+'%')
    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)
于 2012-06-28T11:26:36.290 に答える
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('+@COBDate+','+@FileName+') 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 FOR 句では使用できません
  • 関数内でトランザクションを持つことはできません

ストアド プロシージャ

  • EXEC または EXECUTE を使用する必要があります
  • 出力パラメータを返す
  • テーブルを作成できますが、テーブル変数を返しません
  • SPに参加できません
  • サーバー構成の変更に使用できます
  • XML FOR 句で使用できます
  • SP内で取引可能
于 2012-06-28T11:30:24.470 に答える