2

解决了它(希望!)

我有一个用户定义的表数据类型用作存储过程中的参数。

我对其进行了间谍活动,它引发了如下错误: A column cannot be of a user-defined table type.[16,1]{,1}

不支持吗?如果没有,我对任何人是如何做到的很感兴趣——我的意思是监视一个类似于我的情况的存储过程。

我的数据库服务器是 SQL2008 R2。

下面是复制它的示例代码:

CREATE TYPE [dbo].[UserDefinedTableType] AS TABLE
(
    [col1] INT NULL
    ,[col2] NVARCHAR(MAX) NULL 
)
GO

CREATE PROCEDURE dbo.Bar
    @ItemsToProcess UserDefinedTableType READONLY
AS
GO

CREATE PROCEDURE dbo.Foo
    @ItemsToProcess UserDefinedTableType READONLY
AS 
    EXEC dbo.Bar @ItemsToProcess = @ItemsToProcess  
GO

CREATE PROCEDURE [testDatabase].[test spy stored procedure using user-defined table type]
AS
    DECLARE @items AS UserDefinedTableType
    EXEC tSQLt.SpyProcedure 'dbo.Bar';

    EXEC [dbo].[Foo] @ItemsToProcess = @items;
GO

EXEC tSQLt.Run '[testDatabase].[test spy stored procedure using user-defined table type]'

下面的黑客代码。 我已经标记了我的更改。目标是从作为 XML 的表值参数中查询值。注意:代码尚未经过彻底测试。

        ---Build+
        CREATE PROCEDURE tSQLt.Private_CreateProcedureSpy
            @ProcedureObjectId INT,
            @OriginalProcedureName NVARCHAR(MAX),
            @LogTableName NVARCHAR(MAX),
            @CommandToExecute NVARCHAR(MAX) = NULL
        AS
        BEGIN
            DECLARE @Cmd NVARCHAR(MAX);
            DECLARE @ProcParmList NVARCHAR(MAX),
                    @TableColList NVARCHAR(MAX),
                    @ProcParmTypeList NVARCHAR(MAX),
                    @TableColTypeList NVARCHAR(MAX);

            DECLARE @Seperator CHAR(1),
                    @ProcParmTypeListSeparater CHAR(1),
                    @ParamName sysname,
                    @TypeName sysname,
                    @IsOutput BIT,
/*>>>*/             @IsCursorRef BIT,
/*>>>*/             @IsTableType BIT;

        SELECT @Seperator = '', @ProcParmTypeListSeparater = '', 
                @ProcParmList = '', @TableColList = '', @ProcParmTypeList = '', @TableColTypeList = '';

            DECLARE Parameters CURSOR FOR
            SELECT  p.name, t.TypeName, is_output, is_cursor_ref, tp.is_table_type
                    FROM    sys.parameters p CROSS APPLY tSQLt.Private_GetFullTypeName(p.user_type_id,p.max_length,p.precision,p.scale,NULL) t                                      
/*>>>*/                     INNER JOIN sys.types tp
/*>>>*/                             ON p.user_type_id = tp.user_type_id
            WHERE object_id = @ProcedureObjectId;

            OPEN Parameters;

/*>>>*/     FETCH NEXT FROM Parameters INTO @ParamName, @TypeName, @IsOutput, @IsCursorRef, @IsTableType;
            WHILE (@@FETCH_STATUS = 0)
            BEGIN
                IF @IsCursorRef = 0
                BEGIN
                    SELECT @ProcParmList = @ProcParmList + @Seperator + 
                                                CASE WHEN @IsTableType = 1
/*>>>*/                                             THEN '(SELECT * FROM ' + @ParamName + ' for xml path(''''))'
                                                    ELSE 
                                                    @ParamName
                                                END
                                            , 
                           @TableColList = @TableColList + @Seperator + '[' + STUFF(@ParamName,1,1,'') + ']', 
                           @ProcParmTypeList =  @ProcParmTypeList 
                                                + @ProcParmTypeListSeparater 
                                                + @ParamName 
                                                + ' ' 
                                                + @TypeName 
/*>>>*/                                         + CASE WHEN @IsTableType = 1 THEN ' READONLY ' ELSE ' = NULL ' END
                                                + CASE WHEN @IsOutput = 1 THEN ' OUT'  ELSE '' END, 
                           @TableColTypeList = @TableColTypeList + ',[' + STUFF(@ParamName,1,1,'') + '] ' + 
/*>>>*/                           CASE  WHEN @IsTableType = 1 -- If parameter is a user-defined table type.
/*>>>*/                                     THEN 'xml'
                                        WHEN    @TypeName LIKE '%nchar%'
                                                OR @TypeName LIKE '%nvarchar%'                           
                                            THEN 'nvarchar(MAX)'
                                        WHEN @TypeName LIKE '%char%'
                                            THEN 'varchar(MAX)'
                                        ELSE @TypeName
                                  END + ' NULL';

                    SELECT @Seperator = ',';        
                    SELECT @ProcParmTypeListSeparater = ',';
                END
                ELSE
                BEGIN
                    SELECT @ProcParmTypeList = @ProcParmTypeListSeparater + @ParamName + ' CURSOR VARYING OUTPUT';
                    SELECT @ProcParmTypeListSeparater = ',';
                END;

/*>>>*/         FETCH NEXT FROM Parameters INTO @ParamName, @TypeName, @IsOutput, @IsCursorRef, @IsTableType;
            END;

            CLOSE Parameters;
            DEALLOCATE Parameters;

            DECLARE @InsertStmt NVARCHAR(MAX);
            SELECT @InsertStmt = 'INSERT INTO ' + @LogTableName + 
                                 CASE WHEN @TableColList = '' THEN ' DEFAULT VALUES'
                                      ELSE ' (' + @TableColList + ') SELECT ' + @ProcParmList
                                 END + ';';

            SELECT @Cmd = 'CREATE TABLE ' + @LogTableName + ' (_id_ int IDENTITY(1,1) PRIMARY KEY CLUSTERED ' + @TableColTypeList + ');';
            EXEC(@Cmd);

            SELECT @Cmd = 'CREATE PROCEDURE ' + @OriginalProcedureName + ' ' + @ProcParmTypeList + 
                          ' AS BEGIN ' + 
                             @InsertStmt + 
                             ISNULL(@CommandToExecute, '') + ';' +
                          ' END;';
            EXEC(@Cmd);

            RETURN 0;
        END;
        ---Build-
4

0 回答 0