在对我们项目中的错误进行调查时,我发现了一些对我来说很奇怪的行为。 检查代码:
--CREATE TYPE dbo.test AS TABLE(DocumentVersionId INT, ResourceId INT, Deadline DATE)
DECLARE @documents dbo.test
DECLARE @resourceId INT
INSERT INTO @documents(DocumentVersionId, ResourceId, Deadline)
SELECT * FROM (VALUES(1, 1, GETDATE()),(2, 2, GETDATE()),(3, 3, GETDATE())) T(A, B, C)
DECLARE mails CURSOR FAST_FORWARD FOR
SELECT DISTINCT ResourceId
FROM @documents
OPEN mails
FETCH NEXT FROM mails INTO @resourceId
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE @docs dbo.test
--DELETE FROM @docs
INSERT INTO @docs(DocumentVersionId, Deadline)
SELECT DocumentVersionId, Deadline
FROM @documents
WHERE ResourceId = @resourceId
SELECT * FROM @docs
FETCH NEXT FROM mails INTO @resourceId
END
CLOSE mails
DEALLOCATE mails
我们有为TVP传输的数据生成邮件的程序。必须在循环(游标)中执行此过程的每次执行才能过滤数据。 问题是,在每次循环迭代中,@ docs变量包含来自先前迭代的数据,即使每次重新创建变量也是如此。
我们每次都可以从这个变量中删除数据,但这不是我们期望的行为。 问题是,为什么会发生这种情况?
答案 0 :(得分:1)
变量没有局部范围。来自docs:
变量的范围是可以引用变量的Transact-SQL语句的范围。变量的范围从声明它的位置开始持续到声明它的批处理或存储过程的结束。
这意味着@docs
在第一次循环迭代的范围内,直到过程终止。这或多或少是范围在VB6中的工作方式,它确实创造了一些......有趣的范围问题。
您必须在每次迭代中调用DELETE FROM @docs;
来清除它