sql-server-2008 – 使用* tables *作为表值参数(TVP)

MS sql 2008支持TVP:一种有用的功能,用于批量上传数据到存储的进程进行处理.

而不是创建用户定义的类型,是否可以利用现有的表定义?例如,是否可以使用以下签名创建存储的进度?

CREATE PROCEDURE usp_InsertProductionLocation
@TVP **LocationTable** READONLY

文档似乎表明这是不可能的.

示例代码

/*
Sample code from:
http://msdn.microsoft.com/en-us/library/bb510489.aspx
*/

USE AdventureWorks2008R2;
GO

/* Create a table type. */
CREATE TYPE LocationTableType AS TABLE 
( LocationName VARCHAR(50),CostRate INT );
GO

/* Create a procedure to receive data for the table-valued parameter. */
CREATE PROCEDURE usp_InsertProductionLocation
    @TVP LocationTableType READONLY
    AS 
    SET NOCOUNT ON
    INSERT INTO [AdventureWorks2008R2].[Production].[Location]
           ([Name],[CostRate],[Availability],[ModifiedDate])
        SELECT *,GETDATE()
        FROM  @TVP;
        GO

/* Declare a variable that references the type. */
DECLARE @LocationTVP 
AS LocationTableType;

/* Add data to the table variable. */
INSERT INTO @LocationTVP (LocationName,CostRate)
    SELECT [Name],0.00
    FROM 
    [AdventureWorks2008R2].[Person].[StateProvince];

/* Pass the table variable data to a stored procedure. */
EXEC usp_InsertProductionLocation @LocationTVP;
GO

/*
The following is not part of the original source code:
*/

CREATE TABLE LocationTable(
 LocationName VARCHAR(50),CostRate INT );
GO

解决方法

不,您无法利用现有的表定义,您需要定义显式类型.这在2007年被要求关闭,因为“无法修复”而被关闭但我仍然强烈建议您进行投票并留下评论来描述您的用例以及这将如何帮助您的业务提高效率.你甚至可以指出这个问题,以证明尝试和自动化它是多么乏味.

Item on UserVoice (Formerly Connect #294130)

你今天可以动态地做到这一点,但是…例如你的简单定义:

-- you would pass these two in as parameters of course:
DECLARE
  @TableName SYSNAME = N'LocationTable',@TypeName  SYSNAME = N'LocationTypeTable';

DECLARE @sql NVARCHAR(MAX) = N'';

SELECT @sql = @sql + N',' + CHAR(13) + CHAR(10) + CHAR(9) 
    + QUOTENAME(c.name) + ' '
    + s.name + CASE WHEN LOWER(s.name) LIKE '%char' THEN 
        '(' + CONVERT(VARCHAR(12),(c.max_length/
        (CASE LOWER(LEFT(s.name,1)) WHEN N'n' THEN 2 ELSE 1 END))) + ')' 
        ELSE '' END
        -- need much more conditionals here for other data types
    FROM sys.columns AS c
    INNER JOIN sys.types AS s
    ON c.system_type_id = s.system_type_id
    AND c.user_type_id = s.user_type_id
    WHERE c.[object_id] = OBJECT_ID(@TableName);

SELECT @sql = N'CREATE TYPE ' + @TypeName
    + ' AS TABLE ' + CHAR(13) + CHAR(10) + '(' + STUFF(@sql,1,'')
    + CHAR(13) + CHAR(10) + ');';

PRINT @sql;
-- EXEC sp_executesql @sql;

结果:

CREATE TYPE LocationTypeTable AS TABLE 
(
    [LocationName] varchar(50),[CostRate] int
);

免责声明:这不涉及MAX类型,数字精度和数字等各种其他因素.最终解决方案必须更加健壮,以考虑所有潜在的列定义,但这应该给你一个开始.

sql Server 2012中,有新的DMV和存储过程,可以更容易地从现有表(或存储过程甚至即席查询)派生列元数据,而不必混淆sys.types和sys的所有条件逻辑.列.我blogged briefly about these enhancements in December.它仍然很乏味,但它介于上面可怕的不可维护的意大利面和只能说“作为[表x]的副本”的能力……

相关文章

SELECT a.*,b.dp_name,c.pa_name,fm_name=(CASE WHEN a.fm_n...
if not exists(select name from syscolumns where name=&am...
select a.*,pano=a.pa_no,b.pa_name,f.dp_name,e.fw_state_n...
要在 SQL Server 2019 中设置定时自动重启,可以使用 Window...
您收到的错误消息表明数据库 'EastRiver' 的...
首先我需要查询出需要使用SQL Server Profiler跟踪的数据库标...