在动态SQL查询中更新TableType变量

时间:2014-01-29 07:26:45

标签: sql sql-server sql-update dynamic-sql user-defined-types

我在我的数据库中创建了用户定义的表类型。之后我在我的程序中声明了该表类型的变量。而且我已经回归了其余的逻辑。最后,我尝试使用动态SQL更新该表类型变量。

但我收到了一个错误:

  

Msg 10700,Level 16,State 1,Line 1
  表值参数“@ttbl_TagList”是READONLY,不能修改。

如何解决错误?

用户定义的表格类型:

CREATE TYPE [dbo].[tt_TagList] AS TABLE(
    [tagListId] [tinyint] IDENTITY(1,1) NOT NULL,
    [tagId] [tinyint] NOT NULL DEFAULT ((0)),
    [tagName] [varchar](100) NOT NULL DEFAULT (''),
    [tagValue] [nvarchar](max) NOT NULL DEFAULT ('')
)
GO

步骤:

CREATE PROCEDURE [dbo].[P_ReplaceTemplateTag]   
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE @ttbl_TagList dbo.tt_TagList, @V_TagId INT, @V_Counter TINYINT = 1, 
            @V_FinalQuery NVARCHAR(MAX) = '', @V_TagValue NVARCHAR(MAX); 

    INSERT INTO @ttbl_TagList (tagId, tagName, tagValue) 
    SELECT DISTINCT T.tagId, T.tagName, '' AS tagValue 
    FROM dbo.tbl_Tag T;

    WHILE (1 = 1)
    BEGIN
        SET @V_TagValue = '';
        SELECT @V_TagId = tagId FROM @ttbl_TagList WHERE tagListId = @V_Counter;

        IF (@@ROWCOUNT = 0) 
        BEGIN 
            BREAK;
        END

        IF (@V_TagId = 1) 
        BEGIN 
            /* Logic for getting tag value */
            SET @V_TagValue = 'Tag Value 1';
        END
        ELSE IF (@V_TagId = 2) 
        BEGIN 
            /* Logic for getting tag value */
            SET @V_TagValue = 'Tag Value 2';
        END
        ELSE IF (@V_TagId = 3) 
        BEGIN 
            /* Logic for getting tag value */
            SET @V_TagValue = 'Tag Value 3';
        END
        ELSE IF (@V_TagId = 4) 
        BEGIN 
            /* Logic for getting tag value */
            SET @V_TagValue = 'Tag Value 4';
        END

        IF (@V_TagValue != '')
        BEGIN 
            SET @V_FinalQuery = @V_FinalQuery + ' WHEN ' + CONVERT(NVARCHAR(10), @V_Counter) + ' THEN ''' + @V_TagValue + '''';
        END
        SET @V_Counter = @V_Counter + 1;
    END

    IF (@V_FinalQuery != '')
    BEGIN
        SET @V_FinalQuery = N'UPDATE @ttbl_TagList SET tagValue = (CASE tagListId' + @V_FinalQuery + ' END)';
        EXECUTE sp_executesql @V_FinalQuery, N'@ttbl_TagList dbo.tt_TagList readonly', @ttbl_TagList;
    END

    SELECT * FROM @ttbl_TagList;
END 

1 个答案:

答案 0 :(得分:0)

TVP无法直接更新。所以试试这个 -

CREATE PROCEDURE [dbo].[P_ReplaceTemplateTag]   
AS
BEGIN
    SET NOCOUNT ON;

    IF OBJECT_ID('tempdb.dbo.#t1') IS NOT NULL
        DROP TABLE #t1

    DECLARE 
          @ttbl_TagList dbo.tt_TagList
        , @V_Counter TINYINT = 1
        , @V_FinalQuery NVARCHAR(MAX) = ''
        , @V_TagValue NVARCHAR(MAX); 

    INSERT INTO @ttbl_TagList (tagId, tagName, tagValue) 
    SELECT DISTINCT tagId, tagName, ''
    FROM dbo.tbl_Tag;

    WHILE (1 = 1) BEGIN

        SELECT @V_TagValue = 
            CASE 
                WHEN tagId = 1 THEN 'Tag Value 1'
                WHEN tagId = 2 THEN 'Tag Value 2'
                WHEN tagId = 3 THEN 'Tag Value 3'
                WHEN tagId = 4 THEN 'Tag Value 4'
                ELSE ''
            END
        FROM @ttbl_TagList 
        WHERE tagListId = @V_Counter;

        IF (@@ROWCOUNT = 0) BREAK;

        IF (@V_TagValue != '')
        BEGIN 
            SET @V_FinalQuery = @V_FinalQuery + ' WHEN ' + CONVERT(NVARCHAR(10), @V_Counter) + ' THEN ''' + @V_TagValue + '''';
        END

        SET @V_Counter = @V_Counter + 1;
    END

    IF (@V_FinalQuery != '')
    BEGIN

        CREATE TABLE #t1
        (
              tagId TINYINT
            , tagName VARCHAR(100)
            , tagValue NVARCHAR(MAX)
        )

        SET @V_FinalQuery = N'
            INSERT INTO #t1
            SELECT tagId, tagName, (CASE tagListId' + @V_FinalQuery + ' END)
            FROM @ttbl_TagList';

        EXEC sys.sp_executesql 
              @V_FinalQuery
            , N'@ttbl_TagList dbo.tt_TagList readonly'
            , @ttbl_TagList;

    END

    SELECT * FROM #t1;

END