Нужна помощь в выборе курсора, как будто это рабочий стол - PullRequest
0 голосов
/ 01 октября 2019

У меня есть хранимая процедура, которую я пытаюсь написать, и я хотел использовать курсор в качестве рабочего стола, чтобы я мог использовать результаты для обновления таблицы. Это бросает несколько ошибок. Кто-нибудь сможет помочь мне решить эти проблемы?

create or replace PROCEDURE SP_POPULATE_STUDENT_STOPTEMPID

AS

CURSOR c_workTable IS
SELECT  
    stdnt.STUDENT_ID, 
    stdnt.route_code, 
    stdnt.DISPATCH_TYPE, 
    stdnt.RUN_CODE, 
    stdnt.STOP_ADDRESS, 
    stdnt.STOP_TIME, 
    ST.STOP_TEMPLATE_ID 
FROM  
    STOP_TEMPLATE ST 
    JOIN TASK_TEMPLATE TT 
        ON ST.TASK_TEMPLATE_ID = TT.TASK_TEMPLATE_ID 
    JOIN RUN_TEMPLATE RT 
        ON ST.RUN_TEMPLATE_ID = RT.RUN_TEMPLATE_ID,  
    STUDENT stdnt
WHERE 
    TT.TASK_NAME = stdnt.route_code 
    AND TT.DISPATCH_TYPE = stdnt.DISPATCH_TYPE 
    AND RT.RUN_CODE = stdnt.RUN_CODE 
    AND ST.STOP_DESCRIPTION = stdnt.STOP_ADDRESS 
    AND CAST(ST.EXPECTED_ARRIVAL_TIME AS TIME(7)) = stdnt.STOP_TIME ;

BEGIN

UPDATE STUDENT stdnt  
SET stdnt.STOP_TEMPLATE_ID = c_workTable .STOP_TEMPLATE_ID 
FROM  
    c_workTable 
WHERE  
    stdnt.STUDENT_ID = c_workTable .STUDENT_ID 
    AND stdnt.route_code = c_workTable .route_code 
    AND stdnt.DISPATCH_TYPE = c_workTable .DISPATCH_TYPE 
    AND stdnt.RUN_CODE = c_workTable .RUN_CODE 
    AND stdnt.STOP_ADDRESS = c_workTable .STOP_ADDRESS     
    AND stdnt.STOP_TIME = c_workTable .STOP_TIME 


END SP_POPULATE_STUDENT_STOPTEMPID;

ETA: изменил некоторые имена переменных в запросе

Я написал это на основе хранимой процедуры на сервере sql, но получаю несколькоошибки в операторе обновления.

On UPDATE STUDENT stdnt

Ошибка (30,5): PL / SQL: оператор SQL игнорируется

Затем включениз предложения from я получаю эту ошибку

Ошибка (32,5): PL / SQL: ORA-00933: команда SQL неправильно завершена

Наконец, в предложении ENDЯ получаю

Ошибка (42,35): PLS-00103: Обнаружен символ «конец файла» при ожидании одного из следующих действий: (начало регистра объявляет завершение исключения конца для цикла goto ifmod null прагма повышение возвращение выбрать обновление при
<< продолжить закрыть текущий удалить блокировку выборки <br>вставить открытый набор точек сохранения отката sql выполнить коммит для очистки канала слияния

--new code
UPDATE(
SELECT stdnt.STOP_TEMPLATE_ID as old_val,
ST.STOP_TEMPLATE_ID as new_val
FROM STUDENT stdnt
    JOIN STOP_TEMPLATE ST 
    JOIN TASK_TEMPLATE TT 
        ON ST.TASK_TEMPLATE_ID = TT.TASK_TEMPLATE_ID 
    JOIN RUN_TEMPLATE RT 
        ON ST.RUN_TEMPLATE_ID = RT.RUN_TEMPLATE_ID
    JOIN STUDENT stdnt
        ON (TT.TASK_NAME = stdnt.route_code 
            AND TT.DISPATCH_TYPE = stdnt.DISPATCH_TYPE 
            AND RT.RUN_CODE = stdnt.RUN_CODE 
            AND ST.STOP_DESCRIPTION = stdnt.STOP_ADDRESS 
            AND CAST(ST.EXPECTED_ARRIVAL_TIME AS TIMESTAMP(7)) = 
stdnt.STOP_TIME)
) t
SET t.old_val = t.new_val;

Ответы [ 2 ]

1 голос
/ 01 октября 2019

Другой и лучший способ - использовать оператор MERGE в ORACLE для обновления таблицы из 2 или более таблиц -

MERGE INTO STUDENT stdnt
USING (SELECT  SRM.STUDENT_ID, 
               SRM.route_code, 
               SRM.DISPATCH_TYPE, 
               SRM.RUN_CODE, 
               SRM.STOP_ADDRESS, 
               SRM.STOP_TIME, 
               ST.STOP_TEMPLATE_ID 
       FROM STOP_TEMPLATE ST 
       JOIN TASK_TEMPLATE TT ON ST.TASK_TEMPLATE_ID = TT.TASK_TEMPLATE_ID 
       JOIN RUN_TEMPLATE RT ON ST.RUN_TEMPLATE_ID = RT.RUN_TEMPLATE_ID,  
       STUDENT_ROUTE_MAPPING SRM 
       WHERE TT.TASK_NAME = SRM.route_code 
       AND TT.DISPATCH_TYPE = SRM.DISPATCH_TYPE 
       AND RT.RUN_CODE = SRM.RUN_CODE 
       AND ST.STOP_DESCRIPTION = SRM.STOP_ADDRESS 
       AND CAST(ST.EXPECTED_ARRIVAL_TIME AS TIME(7)) = SRM.STOP_TIME) I
ON (stdnt.STUDENT_ID = I.STUDENT_ID 
    AND stdnt.route_code = I.route_code 
    AND stdnt.DISPATCH_TYPE = I.DISPATCH_TYPE 
    AND stdnt.RUN_CODE = I.RUN_CODE 
    AND stdnt.STOP_ADDRESS = I.STOP_ADDRESS     
    AND stdnt.STOP_TIME = I.STOP_TIME)
WHEN MATCHED THEN UPDATE
                  SET stdnt.STOP_TEMPLATE_ID = I.STOP_TEMPLATE_ID
0 голосов
/ 01 октября 2019

Этого можно добиться с помощью одного оператора UPDATE, который использует JOIN:

UPDATE(
    SELECT  
        stdnt.STOP_TEMPLATE_ID as old_val 
      , ST.STOP_TEMPLATE_ID as new_val
    FROM  
        STOP_TEMPLATE ST 
        JOIN TASK_TEMPLATE TT 
            ON ST.TASK_TEMPLATE_ID = TT.TASK_TEMPLATE_ID 
        JOIN RUN_TEMPLATE RT 
            ON ST.RUN_TEMPLATE_ID = RT.RUN_TEMPLATE_ID
        JOIN STUDENT stdnt
            ON (    TT.TASK_NAME = stdnt.route_code 
                AND TT.DISPATCH_TYPE = stdnt.DISPATCH_TYPE 
                AND RT.RUN_CODE = stdnt.RUN_CODE 
                AND ST.STOP_DESCRIPTION = stdnt.STOP_ADDRESS 
                AND CAST(ST.EXPECTED_ARRIVAL_TIME AS TIME(7)) = stdnt.STOP_TIME)
) t
SET t.old_val = t.new_val;

Ссылка на другой вопрос и ответы, которые могут помочь: Обновление оператора с внутренним объединением в Oracle .

Альтернативным, но похожим решением было бы получить значение для обновления из подзапроса:

UPDATE STUDENT stdnt
   SET stdnt.STOP_TEMPLATE_ID = (
    SELECT  
        ST.STOP_TEMPLATE_ID
    FROM  
        STOP_TEMPLATE ST 
        JOIN TASK_TEMPLATE TT 
            ON (ST.TASK_TEMPLATE_ID = TT.TASK_TEMPLATE_ID 
                AND TT.TASK_NAME = stdnt.route_code 
                AND TT.DISPATCH_TYPE = stdnt.DISPATCH_TYPE)
        JOIN RUN_TEMPLATE RT 
            ON (ST.RUN_TEMPLATE_ID = RT.RUN_TEMPLATE_ID
                AND RT.RUN_CODE = stdnt.RUN_CODE)
    WHERE ST.STOP_DESCRIPTION = stdnt.STOP_ADDRESS 
      AND CAST(ST.EXPECTED_ARRIVAL_TIME AS TIME(7)) = stdnt.STOP_TIME
);

Ссылка на ответ по связанной проблеме с аналогичным решением: ORA-00933: команда SQL неправильно завершилась ошибка в операторе обновления

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...