Informix: для цикла - PullRequest
       4

Informix: для цикла

1 голос
/ 16 марта 2012

Мне нужно написать сохраненный процесс, который будет принимать строку идентификаторов фильмов, разделенных запятыми, и получит мне список названий фильмов из дБ.Я пытался, но я не уверен, что синтаксис правильный, очевидно, дб Vis выдает синтаксическую ошибку

Pl.Help.

  Code:

CREATE PROCEDURE test_sp() returning VARCHAR(255);
begin


define set_movieIds, t_movieNames varchar(255);
define t_movieID varchar(5);
define t_count, t_length integer;


let set_movieIds = '54565' ||',' || '55258' || ',' || '55711' || ',' ||'52719' || ',';
let t_length = length(set_movieIds);

for t_count IN (0 TO t_length) loop
        IF(set_movieIds[t_count] is not ',')
                THEN

                 for t_count in (t_count to t_count+4)
                     let t_movieID[t_count] = set_movieIds[t_count]
                 end for;

                select movie_name into t_movieNames 
                from tbl_cinemasource_movieinfo 
                where movie_id = t_movieID      
                let t_movieNames = t_movieNames || ',';

        end if;


exit when t_count = t_length;
end loop;


return t_movieNames;
end;
END PROCEDURE;

1 Ответ

4 голосов
/ 19 марта 2012

Здесь есть множество проблем.

CREATE PROCEDURE test_sp() returning VARCHAR(255);

    begin

Это BEGIN не является абсолютно неправильным, но оно является обычным и ненужным.

    define set_movieIds, t_movieNames varchar(255);
    define t_movieID varchar(5);
    define t_count, t_length integer;

    let set_movieIds = '54565' ||',' || '55258' || ',' || '55711' || ',' ||'52719' || ',';

Почему бы не простой литерал? А почему запятая? Однако это косметические, а не функциональные проблемы.

    let t_length = length(set_movieIds);

    for t_count IN (0 TO t_length) loop

Это не поддерживаемая нотация в Informix SPL (язык хранимых процедур). Вы бы написали более обычный цикл как:

    FOR t_count = 0 TO t_length

Продолжение ...

        IF (set_movieIds[t_count] is not ',') THEN

IS NOT в значительной степени должен следовать NULL (хотя Standard SQL допускает также TRUE, FALSE или UNKNOWN). Но вы все равно ищете оператора «не равных». Скобки не обязательны.

        IF set_movieIds[t_count] != ',' THEN

Добавление: Одна из менее удовлетворительных особенностей SPL заключается в том, что строковые индексы, написанные с использованием записи нижнего индекса, могут иметь только постоянные целые числа как индексы. К счастью, есть способ обойти эту проблему, используя вместо этого функцию SUBSTR ():

        IF SUBSTR(set_movieIds, t_count, 1) != ',' THEN

Продолжение ...

             for t_count in (t_count to t_count+4)

Синтаксически это должно быть:

             FOR t_count = t_count TO t_count+4

Семантически, это вызывает у меня головную боль. Вам нужна дополнительная переменная для этого внутреннего цикла;

             FOR u_count = t_count TO t_count+4

Продолжение ...

                 let t_movieID[t_count] = set_movieIds[t_count]
             end for;

Мне не понятно, что вы пытаетесь скопировать. Я думаю, что вам может понадобиться переменная, начинающаяся с 1 (я назову ее v_count) и u_count, а затем:

                 LET t_movieID[v_count] = set_movieIds[u_count];
                 LET v_count = v_count + 1;

[Это тоже нужно будет отрегулировать.]

Вы можете быть в порядке без точки с запятой после LET, а может и нет. Несоответствие здесь сводит меня с ума.

Продолжение ...

            select movie_name into t_movieNames 
            from tbl_cinemasource_movieinfo 
            where movie_id = t_movieID    

Вам понадобится точка с запятой после оператора SELECT.

            let t_movieNames = t_movieNames || ',';

        end if;

    exit when t_count = t_length;

Это обозначение не является частью SPL. Вы должны написать:

    IF t_count = LENGTH THEN EXIT FOR; END IF;

(Возможно, вам не нужны обе эти точки с запятой.) OTOH, вы также собираетесь перейти к следующему циклу цикла FOR. С введением u_count выше, вам может понадобиться настроить t_count.

    end loop;

Вы должны написать END FOR, чтобы завершить цикл FOR; вы пишете END IF, чтобы завершить оператор IF; вы пишете END XYZ для завершения конструкции XYZ. Это, по крайней мере, соответствует.

    return t_movieNames;
    end;

END PROCEDURE;

Так много для рассечения того, что там. С учетом сказанного, это действительно неудобно. Обычно я хотел бы написать краткую процедуру, которая возвращала бы каждый фильм как отдельный результат. Я также хотел бы использовать что-то кроме строки для описания фильмов, которые будут выбраны. Поскольку список здесь жестко запрограммирован, я бы изменил инструкцию SELECT, чтобы использовать список IN. Если список является переменным, я бы использовал временную таблицу, заполненную идентификаторами фильмов, которые мне нужны. Это будет создано вне этой процедуры. В качестве альтернативы, если вы используете текущую (поддерживаемую) версию Informix Dynamic Server (вместо IDS 7.x или OnLine 5.20), то вы можете использовать набор целых чисел (или VARCHAR (5)) для описания списка фильмы.

Таким образом, в простейшем случае я бы имел:

CREATE PROCEDURE test_sp() RETURNING VARCHAR(255) AS movieName;

    DEFINE t_movieNames varchar(255);

    FOREACH SELECT movie_name
              INTO t_movieNames 
              FROM tbl_cinemasource_movieinfo 
             WHERE movie_id IN (54565, 55258, 55711, 52719)
        RETURN t_movieNames WITH RESUME;
    END FOREACH;

END PROCEDURE;
...