2016-02-23 3 views
0

Во время расследования ошибки в нашем проекте я натолкнулся на какое-то странное поведение. Проверьте код:объявить переменную настраиваемого типа в цикле курсора

--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 содержит данные предыдущих итераций, даже когда переменная воссоздает каждый раз.

Мы можем удалять данные из этой переменной каждый раз, но это не то поведение, которое мы ожидаем. Вопрос в том, почему это происходит?

enter image description here

+0

Вы предполагаете, что @docs имеет локальную область видимости. Вы уверены, что это действительно правильно? –

+0

Мне немного странно, что во время компиляции он не поднимает _ «переменная, уже определенная» _ –

ответ

1

Переменные не имеют локальную область видимости. От docs:

Объем переменной - это диапазон операторов Transact-SQL, которые могут ссылаться на переменную. Объем переменной длится от той точки, которую объявляется до конца партии или хранимой процедуры, в которой она объявлена.

Это означает, что @docs находится в области видимости от первой итерации цикла до тех пор, пока процедура не завершится. Это больше или меньше, чем объем работы в VB6, и это создало некоторые ... интересные проблемы.

Вы должны будете звонить DELETE FROM @docs; в каждой итерации, чтобы очистить его

Смежные вопросы