在单行中创建并传递表值参数

big*_*mac 6 sql-server stored-procedures table-valued-parameters

使用SQL Server 2012,是否可以省略声明表值参数(TVP)只是为了将其传递给存储过程?下面是一个存储过程(SP)的一个非常简单的例子,它采用TVP和一个工作示例来执行该SP,我必须声明TVP,填充它然后将其传递给SP.我希望能够简单地将人口标准直接传递给EXEC电话.这可能吗?

场景设置:

-- Create a sample Users table
CREATE TABLE Users (UserID int, UserName varchar(20))
INSERT INTO Users VALUES (1, 'Bob'), (2, 'Mary'), (3, 'John'), (4, 'Mark')

-- Create a TVP Type
CREATE TYPE UserIdTableType AS TABLE (UserID int)

-- Create SP That Uses TVP Type
CREATE PROCEDURE GetUsers
@UserIdFilter UserIdTableType READONLY
AS
    SELECT * FROM @UserIdFilter WHERE UserID > 2
Run Code Online (Sandbox Code Playgroud)

执行的工作方法:

DECLARE @MyIds AS UserIdTableType
INSERT INTO @MyIds SELECT UserID FROM Users
EXEC GetUsers @MyIds
Run Code Online (Sandbox Code Playgroud)

要求执行的方法:

EXEC GetUsers (SELECT UserID FROM Users)
Run Code Online (Sandbox Code Playgroud)

Sol*_*zky 5

不,你不能创建一个内联TVP或CAST/CONVERT它.这不是一个"数据类型"之类INT,VARCHAR,DATETIME等; 它是一种完全不同的"表类型".用户定义的表类型(UDTT)只是元数据,用作表变量声明的定义/模式.当这样的表变量用作输入参数时,该用法被认为是TVP(表值参数).但事情仍然是一个表变量,其定义存储在其中tempdb.这是一个物理结构,而不是一个内存结构,你不能CASTCONVERT一个表,无论是真实的,临时的还是变量的.

虽然问题中给出的示例是简单的,只是为了让想法得以实现,但看起来您的总体目标似乎是代码重用/创建子例程(否则您可以轻松完成SELECT * FROM Users WHERE UserID > 2).不幸的是,T-SQL不允许使用非常优雅/干净的代码,因此您必须接受一定程度的重复和/或笨拙.

但是,如果结果集至少具有必需的字段,则可以为结果集制作稍微通用的处理程序.你可以

  • 传入XML参数,或
  • 将结果转储到临时表并在子proc调用中引用它(不需要是动态SQL),因此不需要传入任何参数(至少不是一个用于数据集/结果/查询)

在这两种情况下,结构比使用TVP更灵活,因为TVP必须是那些确切的字段.但是,引用假定存在的临时表允许类似于以下内容:

PROC_1

SELECT *
INTO #MyTemp
FROM sys.tables;

EXEC dbo.Proc_4 @StartsWith = 'a', @HowMany = 10;
Run Code Online (Sandbox Code Playgroud)

Proc_2

SELECT *
INTO #MyTemp
FROM sys.columns;

EXEC dbo.Proc_4 @StartsWith = 'bb', @HowMany = 20;
Run Code Online (Sandbox Code Playgroud)

Proc_3

SELECT *
INTO #MyTemp
FROM sys.views;

EXEC dbo.Proc_4 @StartsWith = 'ccc', @HowMany = 33;
Run Code Online (Sandbox Code Playgroud)

Proc_4

SELECT TOP (@HowMany) tmp.*
FROM   #MyTemp tmp
WHERE  tmp.[name] LIKE @StartsWith + '%'
ORDER BY tmp.[object_id] ASC;
Run Code Online (Sandbox Code Playgroud)