【发布时间】:2011-08-04 23:13:39
【问题描述】:
MSDN Docs on table-valued Sql Clr functions 声明:
Transact-SQL 表值函数 实现调用的结果 函数到一个中间表。 ... 相比之下,CLR 表值 函数代表一个流 选择。没有要求 整个结果集是 在单个表中实现。这 IEnumerable 对象返回的 托管函数直接调用 查询的执行计划 调用表值函数,并且 结果被消耗在一个 增量方式。 ...这也是一个 如果你有更好的选择 返回大量行, 因为他们不必 整体在记忆中具体化。
Then I find out that no data access is allowed in the 'Fill row' method。这意味着您仍然必须在 init 方法中完成所有数据访问并将其保存在内存中,等待调用“填充行”。我误解了什么吗? 如果我不将结果强制放入数组或列表中,我会收到错误消息:'ExecuteReader 需要一个打开且可用的连接。连接的当前状态为关闭。'
代码示例:
[<SqlFunction(DataAccess = DataAccessKind.Read, FillRowMethodName = "Example8Row")>]
static member InitExample8() : System.Collections.IEnumerable =
let c = cn() // opens a context connection
// I'd like to avoid forcing enumeration here:
let data = getData c |> Array.ofSeq
data :> System.Collections.IEnumerable
static member Example8Row ((obj : Object),(ssn: SqlChars byref)) =
do ssn <- new SqlChars(new SqlString(obj :?> string))
()
我在这里处理几百万行。有没有办法懒惰地做到这一点?
【问题讨论】:
-
我阅读文档的方式似乎暗示使用表值函数生成整个结果集并将其放在某个地方 - 如果它很小,可能是内存,否则是 tempdb - 在其结果返回到客户。使用 CLR,只要有一些记录可用,结果集就可以开始直接从内存缓冲区返回给客户端。我不知道这是否是您需要明确担心的事情。我认为 MSDN 只是在解释这两种表函数的内部工作原理。除非我误解了这篇文章。
-
我相信
yield return在 C# 中工作。我希望seq { }能够类似地工作。没有? -
@Daniel - 这就是我正在尝试的。我想删除 '|> Array.ofSeq' 并改用 yield return ,但这会导致我出现这个错误。这就是这个问题的意义所在。让步时,在 Example8Row 函数中执行数据访问,这似乎是不允许的。
-
@Yuck and Robert:是的,“流式传输”部分是指在方法结束之前使用
yield return将结果发回的能力。这是您可以做的一个选项,或者您可以建立集合并在方法结束时将其全部发回。对于 T-SQL 多语句 TVF,别无选择。他们所能做的就是将结果建立在一个只能在函数结束时返回的表变量中。
标签: sql-server f# sqlclr