1

テーブル名と id 値が渡される関数を作成しようとしています。プロシージャは、指定された行のすべてのフィールド値を含む単一の文字列を返します。参照されるすべてのテーブルには、「Id」というフィールドがあります。テーブル内の指定された行を連結できる他の例を見つけましたが、テーブルを動的に指定する方法を見つけることができませんでした。以下は、私がここで見つけた最も近い例です:

TSQL: 行内のすべてのフィールドの値を 1 つの文字列に

CREATE FUNCTION udf_GetTableValues (@TableName varchar(MAX) = '',@Id int = 0)
    RETURNS varchar(MAX)
AS
BEGIN
  DECLARE @returnVal varchar(MAX)

  SELECT @ReturnVal = ''
  SELECT @ReturnVal = @ReturnVal 
         + ' // ' 
         + T2.N.value('local-name(.)', 'nvarchar(128)')
         +': '
         + T2.N.value('.', 'nvarchar(max)')
    FROM (SELECT *
            FROM Branch 
           WHERE ID = 1
             FOR XML PATH(''), type) as T1(X)
   CROSS APPLY T1.X.nodes('/*') as T2(N)


  RETURN @ReturnVal  
END
4

1 に答える 1

0

まず最初に、SQL Server が関数内で動的 SQL を許可することを拒否しているという事実を理解する必要があります。残念ですが、回避しなければならない制限です。

テーブルの各行に動的 SQL ロジックを適用する手法を次に示します。

  • 動的 SQL のすべての入力パラメーターと期待される結果を保持する一時テーブルを作成します。
  • 一時テーブルが存在することを既に想定しており、動的 SQL ロジックを適用して一時テーブルの行をループするストアド プロシージャを作成します。
  • 評価するデータを一時テーブルに追加します
  • 動的 SQL プロシージャを実行する
  • 期待される結果をお楽しみください :-)

1) テストデータの設定から始めましょう。

    -- ====================================================================
    -- BEGIN: Setup test data
    -- ====================================================================
    IF OBJECT_ID('Branch', 'U') IS NOT NULL DROP TABLE Branch;
    IF OBJECT_ID('Branch2', 'U') IS NOT NULL DROP TABLE Branch2;
    GO
    CREATE TABLE Branch (
        ID      int
       ,Column1 varchar(20)
       ,Column2 varchar(20)
       ,Column3 varchar(20)
    )
    CREATE TABLE Branch2 (
        ID      int
       ,Column1 varchar(20)
       ,Column2 varchar(20)
       ,Column3 varchar(20)
    )
    SET NOCOUNT ON
    INSERT Branch SELECT 1, 'Hello', 'World', 'I write SQL'
    INSERT Branch SELECT 2, 'I like', 'it to be', 'complicated'

    INSERT Branch2 SELECT 1, 'Hello', 'World', 'I write SQL'
    INSERT Branch2 SELECT 2, 'I like', 'it to be', 'complicated'
    SET NOCOUNT OFF
    GO
    -- ====================================================================
    -- END: Setup test data
    -- ====================================================================

2) 次に、動的 SQL を処理する proc を作成します。

    -- ====================================================================
    -- BEGIN: Proc with dynamic SQL logic
    -- ====================================================================
    IF OBJECT_ID('prcReturnTableData', 'P') IS NOT NULL DROP PROCEDURE prcReturnTableData;
    GO
    CREATE PROCEDURE prcReturnTableData 
    AS

    DECLARE @SQL                    nvarchar(MAX)
           ,@ParameterDefinitions   nvarchar(MAX)
           ,@TableName              varchar(128)
           ,@ID                     int
     SELECT @ParameterDefinitions   = '@ID int'      

    DECLARE @idx int
     SELECT @idx = MIN(idx) FROM #Result

    WHILE @idx IS NOT NULL
      BEGIN
        SELECT @TableName = TableName
              ,@ID        = ID
          FROM #Result
         WHERE idx = @idx

        SELECT @SQL = '
            DECLARE @ReturnVal varchar(MAX)

            SELECT @ReturnVal = ''''
            SELECT @ReturnVal = @ReturnVal 
                  + '' // '' 
                  + T2.N.value(''local-name(.)'', ''nvarchar(128)'')
                  + '': ''
                  + T2.N.value(''.'', ''nvarchar(max)'')
              FROM (
                    SELECT *
                      FROM ' + @TableName + ' 
                     WHERE ID = @ID
                       FOR XML PATH(''''), type
                    ) as T1(X)
             CROSS APPLY T1.X.nodes(''/*'') as T2(N)


             UPDATE #Result SET ReturnVal = @ReturnVal WHERE ID = @ID';

        EXEC sp_executeSQL @SQL, @ParameterDefinitions, @ID = @ID;

        SELECT @idx = MIN(idx) FROM #Result WHERE idx > @idx
    END
    GO
    -- ====================================================================
    -- END: Proc with dynamic SQL logic
    -- ====================================================================

3) 最後に、proc を実行して、必要な結果を取得しましょう。

    -- ====================================================================
    -- BEGIN: Solution to execute dynamic SQL logic on each row of a table
    -- ====================================================================
    -- Create the temp table that the dynamic SQL proc expects
    IF OBJECT_ID('tempdb..#Result', 'U') IS NOT NULL DROP TABLE #Result;
    CREATE TABLE #Result (idx int IDENTITY(1,1), TableName varchar(128) NOT NULL, ID int NOT NULL, ReturnVal varchar(MAX) NULL);

    -- Popluate the temp table with the rows you want to evaluate
    INSERT #Result (TableName, ID)
    SELECT 'Branch', ID FROM Branch
    INSERT #Result (TableName, ID)
    SELECT 'Branch2', ID FROM Branch2

    -- Results before
    SELECT * FROM #Result

    -- Execute the dynamic SQL proc
    EXEC prcReturnTableData

    -- Results after
    SELECT * FROM #Result
    -- ====================================================================
    -- END: Solution to execute dynamic SQL logic on each row of a table
    -- ====================================================================
于 2013-03-16T17:42:09.357 に答える