Курсор Oracle, пробегающий последний объект дважды

Вы должны инициализировать каталог данных, выполнив следующую команду

mysqld --initialize [со случайным корневым паролем]

mysqld --initialize-insecure [с пустым корневым паролем]

9
задан Margaret 22 May 2009 в 04:14
поделиться

4 ответа

You can try this:

OPEN cur_t;
LOOP
  FETCH cur_t INTO v_texttoadd;
  EXIT WHEN cur_t%notfound;
  v_string := v_string || v_texttoadd;
END LOOP;

This works because %notfound is set when FETCH is executed and there aren't any more rows to fetch. In your example you checked %notfound after the concatenation and as a result, you had the duplicate in the end.

24
ответ дан 4 December 2019 в 07:35
поделиться

Правильные ответы уже были даны, но лишь немного уточняю.

Моделирование вашей текущей ситуации:

SQL> declare
  2    cursor cur_t
  3    is
  4    select ename
  5      from emp
  6     where deptno = 10
  7    ;
  8    v_texttoadd emp.ename%type;
  9    v_string    varchar2(100);
 10  begin
 11    open cur_t;
 12    loop
 13      fetch cur_t into v_texttoadd;
 14      v_string := v_string || v_texttoadd;
 15      exit when cur_t%notfound;
 16    end loop
 17    ;
 18    dbms_output.put_line(v_string);
 19  end;
 20  /
CLARKKINGMILLERMILLER

PL/SQL-procedure is geslaagd.

Здесь МИЛЛЕР напечатан дважды. Просто переключив оператор EXIT и присвоение v_string, вы получите желаемый результат:

SQL> declare
  2    cursor cur_t
  3    is
  4    select ename
  5      from emp
  6     where deptno = 10
  7    ;
  8    v_texttoadd emp.ename%type;
  9    v_string    varchar2(100);
 10  begin
 11    open cur_t;
 12    loop
 13      fetch cur_t into v_texttoadd;
 14      exit when cur_t%notfound;
 15      v_string := v_string || v_texttoadd;
 16    end loop
 17    ;
 18    dbms_output.put_line(v_string);
 19  end;
 20  /
CLARKKINGMILLER

PL/SQL-procedure is geslaagd.

Однако ваш код PL / SQL становится проще при использовании курсора для цикла. Затем вы можете пропустить переменную v_texttoadd, и количество строк в вашем цикле уменьшится:

SQL> declare
  2    cursor cur_t
  3    is
  4    select ename
  5      from emp
  6     where deptno = 10
  7    ;
  8    v_string    varchar2(100);
  9  begin
 10    for r in cur_t
 11    loop
 12      v_string := v_string || r.ename;
 13    end loop
 14    ;
 15    dbms_output.put_line(v_string);
 16  end;
 17  /
CLARKKINGMILLER

PL/SQL-procedure is geslaagd.

Вы также можете использовать прямой SQL для выполнения задания. Пример с предложением модели SQL, если вы используете версию 10g или выше:

SQL> select string
  2    from ( select string
  3                , rn
  4             from emp
  5            where deptno = 10
  6            model
  7                  dimension by (rownum rn)
  8                  measures (ename, cast(null as varchar2(100)) string)
  9                  ( string[any] order by rn desc = ename[cv()] || string[cv()+1]
 10                  )
 11         )
 12   where rn = 1
 13  /

STRING
-----------------------------------------------------------------------------------
CLARKKINGMILLER

1 rij is geselecteerd.

С уважением, Роб.

3
ответ дан 4 December 2019 в 07:35
поделиться

Simple answer, though possibly not the best:

OPEN cur_t;
LOOP
    FETCH cur_t INTO v_texttoadd;
    IF cur_t%found THEN
        v_string := v_string || v_texttoadd;
    END IF;
EXIT WHEN cur_t%notfound;
END LOOP;
0
ответ дан 4 December 2019 в 07:35
поделиться

%notfound is set when fetch fails to retrieve a new row.

another possible way (this one avoiding the "if"s and "exit when"s):

OPEN cur_t;
FETCH cur_t INTO v_texttoadd;
WHILE cur_t%found LOOP
    v_string := v_string || v_texttoadd;
    FETCH cur_t INTO v_texttoadd;
END LOOP;
2
ответ дан 4 December 2019 в 07:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: