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]的副本”的能力……