2015-09-15 5 views
0

Я работал над курсором, который выглядит ниже. Я использую SQL Server 2008 R2.Почему сервер sql не может очистить локальный параметр, объявленный в курсоре при циклировании?

Declare @Pnr nvarchar(7) 
DECLARE db_cursor CURSOR FOR 
    SELECT B.Pnr FROM SomeTable B 
OPEN db_cursor 
FETCH NEXT FROM db_cursor INTO @Pnr 
WHILE @@FETCH_STATUS = 0 
BEGIN 
/*some stuff*/ 
declare @Remark nvarchar(max) 
SELECT @Remark=COALESCE(@Remark + ', ', '') + Remark from OtherTable where [email protected] 
/*some stuff*/ 
    FETCH NEXT FROM db_cursor INTO @Pnr 
END 
CLOSE db_cursor 
DEALLOCATE db_cursor 

Я думал, что @Remark будет нулевым снова, если он объявлен каждый цикл. Но запрос сохраняет прежнее значение, если он получает значение null для @Remark

Решение просто, я могу установить нуль для каждого цикла, но мне интересно, почему объявление не очищает локальную переменную в цикле.

Пример:

OtherTable 
-------------- 
Pnr | Remark 
--------------- 
2 | aaaaaaaa 
2 | bbbbbbbb 
2 | cccccccc 
3 | qqqqqqqq 
3 | wwwwwwww 

Результаты:

Pnr | Remark 
------------ 
1 | NULL 
2 | aaaaaaaa, bbbbbbbb, cccccccc 
3 | qqqqqqqq, wwwwwwww 
4 | qqqqqqqq, wwwwwwww = should be NULL 
5 | qqqqqqqq, wwwwwwww = should be NULL 
+1

Объявления переменных не участвуют в потоке управления вообще в T-SQL. Это одна из восхитительных «особенностей» этого языка. –

+0

Действительно. Я думал об этом, как о других языках программирования. Спасибо! – esatemre

ответ

2

Это происходит потому, что при назначении из запроса и есть никакое значение не возвращается, SELECT не будет делать назначение так что значение переменной будет не меняются.

Вместо этого используйте SET, чтобы при возврате значения переменная не была равна NULL.

Однако в вашем случае вы хотите объединить все Remark s для каждого Pnr. Используя CURSOR, вы не можете сделать это, используя SET. Но здесь альтернативный и более быстрый способ:

SELECT 
    s.Pnr, 
    t.Remark 
FROM SomeTable s 
CROSS APPLY(
    SELECT STUFF((
     SELECT ', ' + Remark 
     FROM OtherTable 
     WHERE Pnr = s.Pnr 
     FOR XML PATH(''), type).value('.[1]','nvarchar(max)'), 
    1, 2, '') AS Remark 
)t 
+0

Что вы предлагаете, если бы я хотел бы назначить много переменной из запроса? – esatemre

+0

Избегайте курсоров? Не шутите ... Есть очень мало ситуаций, когда курсор является правильным выбором ... – Shnugo

+0

@ Шнуго, да? Я думаю, вы потеряли свой комментарий. –