SQL Server 2008 中的表值参数 (ADO.NET)

传入的数据行存储在一个表变量中,然后您可以通过使用 Transact-SQL 对该表变量进行操作。

表值参数的大小仅受服务器内存的限制。

说明

表值参数是只可输入的参数;不支持 OUTPUT 关键字。

有关表值参数的更多信息,请参见下列资源。

资源

说明

Table-Valued Parameters (Database Engine)(表值参数 [数据库引擎]),位于 SQL Server 联机丛书中

说明如何创建和使用表值参数。

User-Defined Table Types(用户定义的表类型),位于 SQL Server 联机丛书中

说明用于声明表值参数的用户定义的表类型。

Microsoft SQL Server Database Engine(Microsoft SQL Server 数据库引擎)一节

包含演示如何使用 SQL Server 特性和功能的示例。

在 SQL Server 的早期版本中传递多行

开发人员可以选择使用以下选项,将多个行传递给服务器:

  • 必须使用服务器端逻辑才能将这些单个值组合到表变量或临时表中以进行处理。

  • 此过程要求相应的过程或语句包括验证数据结构和取消捆绑值所需的逻辑。

  • 不过,即使是以包含多个语句的批处理形式提交的,每个语句在服务器上还是会单独执行。

  • 尽管这项技术非常有效,但不支持服务器端处理,除非将数据加载到临时表或表变量中。

创建表值参数类型

User-Defined Table Types(用户定义的表类型)。

下面的语句可创建一个名为 CategoryTableType 的表类型,其中包括 CategoryID 和 CategoryName 列:

CREATE TYPE dbo.CategoryTableType AS TABLE
    ( CategoryID int, CategoryName nvarchar(50) )

请注意,声明表值参数时需要使用 READONLY 关键字。

CREATE PROCEDURE usp_UpdateCategories 
    (@tvpNewCategories dbo.CategoryTableType READONLY)

通过表值参数修改数据 (Transact-SQL)

例如,您可以选择表值参数中的所有行,然后将它们插入到数据库表中;您也可以通过将表值参数联接到要更新的表中来创建更新语句。

在 FROM 子句中将表值参数与 JOIN 一起使用时,您还必须为其提供一个别名,如此处所示,表值参数的别名为“ec”:

 
UPDATE dbo.Categories
    SET Categories.CategoryName = ec.CategoryName
    FROM dbo.Categories INNER JOIN @tvpEditedCategories AS ec
    ON dbo.Categories.CategoryID = ec.CategoryID;

此 Transact-SQL 示例演示如何从表值参数中选择行以在单个基于集的操作中执行 INSERT。

INSERT INTO dbo.Categories (CategoryID, CategoryName)
    SELECT nc.CategoryID, nc.CategoryName FROM @tvpNewCategories AS nc;

表值参数的限制

以下是表值参数的几个限制:

  • 无法将表值参数传递给用户定义的函数。

  • SQL Server 不维护有关表值参数的统计信息。

  • 若要修改传递给表值参数中的存储过程或参数化语句的数据,则必须将数据插入到临时表或表变量中。

  • 无法使用 ALTER TABLE 语句来修改表值参数的设计。

配置 SqlParameter 示例

SqlParameter 以插入数据。

// Configure the command and parameter.
SqlCommand insertCommand = new SqlCommand(
    sqlInsert, connection);
SqlParameter tvpParam = insertCommand.Parameters.AddWithValue(
    "@tvpNewCategories", addedCategories);
tvpParam.SqlDbType = SqlDbType.Structured;
tvpParam.TypeName = "dbo.CategoryTableType";

DbDataReader 中派生的任何对象,将数据行流处理到表值参数,如本代码段所示:

 // Configure the SqlCommand and table-valued parameter.
 SqlCommand insertCommand = new SqlCommand(
   "usp_InsertCategories", connection);
 insertCommand.CommandType = CommandType.StoredProcedure;
 SqlParameter tvpParam = 
    insertCommand.Parameters.AddWithValue(
    "@tvpNewCategories", dataReader);
 tvpParam.SqlDbType = SqlDbType.Structured;

将表值参数传递给存储过程

SqlCommand

// Assumes connection is an open SqlConnection object.
using (connection)
{
// Create a DataTable with the modified rows.
DataTable addedCategories =
  CategoriesDataTable.GetChanges(DataRowState.Added);

// Configure the SqlCommand and SqlParameter.
SqlCommand insertCommand = new SqlCommand(
    "usp_InsertCategories", connection);
insertCommand.CommandType = CommandType.StoredProcedure;
SqlParameter tvpParam = insertCommand.Parameters.AddWithValue(
    "@tvpNewCategories", addedCategories);
tvpParam.SqlDbType = SqlDbType.Structured;

// Execute the command.
insertCommand.ExecuteNonQuery();
}

将表值参数传递给参数化 SQL 语句

TypeName 属性来引用 dbo.CategoryTableType 中定义的类型结构。

说明

如果为表值参数中的标识列提供值,则必须为该会话发出 SET IDENTITY_INSERT 语句。

// Assumes connection is an open SqlConnection.
using (connection)
{
// Create a DataTable with the modified rows.
DataTable addedCategories = CategoriesDataTable.GetChanges(
    DataRowState.Added);

// Define the INSERT-SELECT statement.
string sqlInsert = 
    "INSERT INTO dbo.Categories (CategoryID, CategoryName)"
    + " SELECT nc.CategoryID, nc.CategoryName"
    + " FROM @tvpNewCategories AS nc;"

// Configure the command and parameter.
SqlCommand insertCommand = new SqlCommand(
    sqlInsert, connection);
SqlParameter tvpParam = insertCommand.Parameters.AddWithValue(
    "@tvpNewCategories", addedCategories);
tvpParam.SqlDbType = SqlDbType.Structured;
tvpParam.TypeName = "dbo.CategoryTableType";

// Execute the command.
insertCommand.ExecuteNonQuery();
}

 

使用 DataReader 对行进行流处理

OracleDataReader 结果集作为表值参数传递给存储过程。

// Assumes connection is an open SqlConnection.
// Retrieve data from Oracle.
OracleCommand selectCommand = new OracleCommand(
   "Select CategoryID, CategoryName FROM Categories;",
   oracleConnection);
OracleDataReader oracleReader = selectCommand.ExecuteReader(
   CommandBehavior.CloseConnection);

// Configure the SqlCommand and table-valued parameter.
SqlCommand insertCommand = new SqlCommand(
   "usp_InsertCategories", connection);
insertCommand.CommandType = CommandType.StoredProcedure;
SqlParameter tvpParam =
    insertCommand.Parameters.AddWithValue(
    "@tvpNewCategories", oracleReader);
tvpParam.SqlDbType = SqlDbType.Structured;

// Execute the command.
insertCommand.ExecuteNonQuery();

 

 参考地址:http://msdn.microsoft.com/zh-cn/library/bb675163.aspx

 

相关文章: