为什么我们需要 table 值参数

Why do we need table value parameter

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

Table 值参数对于以 "safe" 的方式将表格数据传递给存储过程或函数是必需的,尤其是从客户端代码(例如 SqlCommandSqlParameter).

主要的替代技术是在调用存储过程之前先创建 INSERT 并将其放入 #temporaryTable,但是临时 table 并不完全是临时的,它们存在于 tempdb 引入了命名空间和并发问题。您还必须使用 Dynamic SQL,因为您无法参数化 table 名称。对于非临时 table,同样的问题也适用。

另外,如果你想将数据传递给一个 FUNCTION 然后你想扔掉然后你不能使用临时 table 因为 FUNCTION 代码是严格的只读:它不能删除临时 table 当它完成时,而 table 值的参数在超出范围后神奇地消失。

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

打个比方,这就像在堆栈上传递变量与在堆上传递变量一样 - 使用堆栈意味着您可以获得自动生命周期管理和所有权语义,而不必担心并发性 - 而使用堆则引入了一个整体大量问题。

一个例子

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

使用临时 tables 你的代码必须这样做:

  1. 创建并打开 SqlConnection.
  2. 创建并开始 TRANSACTION
  3. 新建一个#temporarytable
    • 临时 table 的范围限于当前数据库会话。这对于大多数用途来说是可以的,但这意味着您不能在同一会话中对该临时 table 执行多个并发数据库操作。
  4. LOCK 任何正常的 table 如有必要,您将使用,因为您的操作将跨越多次 SqlCommand 执行。
  5. 从客户端或原始存储过程,执行 INSERT 语句来填充临时 table。如果您从客户端应用程序插入数据,您可能还需要多次执行单行 INSERT 操作 - 这是非常低效的,尤其是在高延迟连接环境中,因为 [=84 使用的 TDS 协议=] 服务器非常健谈(具有讽刺意味的是,您可以使用 SqlCommand 执行单个多行 INSERT 操作,但您必须使用 Table 值参数来包含多行数据).
  6. 调用将使用临时 table.
  7. 的存储过程或 FUNCTION
  8. 如果您要让会话保持活动状态,请拆除 #temporaryTable,或者立即结束会话以防止浪费内存。

但是如果你使用一个 Table 值的参数就简单多了:

  1. 创建并打开 SqlConnection.
  2. 创建并开始 TRANSACTION
  3. 创建将调用存储过程或 FUNCTIONSqlCommand 对象,但您可以直接使用 Table-Valued Parameter 并一次性从客户端填充它.然后,客户端软件通过一次操作将 table 数据流推送到服务器,效率更高。
  4. 存储过程随后运行。无需拆卸或结束会话。