为什么我们需要表值参数

时间:2018-05-05 03:06:24

标签: tsql stored-procedures table-valued-parameters

我们可以访问storedprocedures中的实际表。那么通过参数传递表需要什么?有什么特别的优势吗?

1 个答案:

答案 0 :(得分:3)

表值参数是将表格数据以安全的方式传递给存储过程或函数所必需的,特别是来自客户端代码(例如SqlCommandSqlParameter)。

主要的替代技术是在调用sproc之前首先创建INSERT#temporaryTable,但是临时表并不是临时表,它们存在于tempdb中,它引入了命名空间和并发性的问题。您还必须使用动态SQL,因为您无法参数化表名。对于非临时表,同样的问题也适用。

此外,如果您想要将数据传递给之后要丢弃的FUNCTION,那么您就不能使用临时表,因为FUNCTION代码是严格只读的:当它完成后,它不能删除临时表,而表值参数在超出范围后会神奇地消失。

如果一个FUNCTION想要以相同的只读原因将表格数据传递给另一个函数,也绝对需要:该函数不允许创建#temporarytable,但它可以创建和填充表值参数。

通过类比,它就像在堆栈上传递变量而不是在堆上传递 - 使用堆栈意味着您获得自动生命周期管理和所有权语义,而不需要担心并发性 - 而使用堆引入一大堆问题。

一个例子

假设您的应用程序代码需要将元组列表(或主键列表)传递给存储过程或FUNCTION - 或者现有的sproc或函数需要将数据传递给另一个函数。

使用临时表,您的代码必须这样做:

  1. 创建并打开SqlConnection
  2. 创建并开始TRANSACTION
  3. 制作新的#temporarytable
    • 临时表的范围限定为当前数据库会话。这对于大多数目的来说都没问题,但这意味着您无法在同一会话中对该临时表执行多个并发数据库操作。
  4. LOCK您必要时使用的任何普通表格,因为您的操作将涵盖多个SqlCommand次执行。
  5. 从客户端或原始存储过程中,执行INSERT语句以填充临时表。如果您从客户端应用程序插入数据,则可能需要多次执行单行INSERT操作 - 这非常低效,尤其是在高延迟连接环境中,因为SQL使用的TDS协议服务器非常繁琐(具有讽刺意味的是,您可以使用INSERT执行单个多行SqlCommand操作,但您必须使用表值参数来包含多行数据。)
  6. 调用将使用临时表的sproc或FUNCTION
  7. 如果您要保持会话处于活动状态,请删除#temporaryTable,或立即结束会话以防止浪费内存。
  8. 但是如果你使用Table-Valued参数,它会更简单:

    1. 创建并打开SqlConnection
    2. 创建并开始TRANSACTION
    3. 创建将调用您的sproc或SqlCommand的{​​{1}}对象,但您可以直接使用表值参数,并在一次传递中从客户端填充所有参数。然后,客户端软件通过单一操作将表数据流推送到服务器,效率更高。
    4. 然后sproc跑了。不需要拆卸或会话结束。