Oracle пытается обновить таблицу, присоединившись к неиндексированной таблице - PullRequest
0 голосов
/ 27 февраля 2019

Я пытался найти пример, аналогичный моей проблеме, но не смог воспроизвести решение моего успеха.

У меня есть 2 таблицы, Controller и Actions.

В таблице Actions есть столбцыStep, Script, Description, Wait_Until и Ref_Code.

Таблица контроллеров может быть объединена в таблице действий только с помощью Ref_Code.

Таблица действий не может иметь PK, поскольку для каждого Ref_Code существуетШаг, который необходимо предпринять.

Я получаю сообщение об ошибке при попытке обновить таблицу Controller с помощью оператора слияния:

ORA-30926: невозможно получить стабильный набор строк в исходных таблицах

Мой оператор слияния выглядит следующим образом:

MERGE INTO DSTETL.SHB_FTPS_CONTROLLER ftpsc
     USING (SELECT DISTINCT FTPSC.SESSION_ID,
                            FTPSC.ORDER_DATE,
                            sa.step,
                            sa.next_step,
                            LAST_ACTION_TMSTMP,
                            SA.ACTION_SCRIPT,
                            sa.ref_code,
                            SA.WAIT_UNTIL
              FROM DSTETL.SHB_FTPS_CONTROLLER ftpsc, DSTETL.SHB_ACTIONS sa
             WHERE     SA.REF_CODE = FTPSC.REF_CODE
                   AND SA.STEP > ftpsc.curr_step
                   AND sa.step = ftpsc.next_step) v1
        ON (v1.REF_CODE = FTPSC.REF_CODE)
WHEN MATCHED
THEN
   UPDATE SET FTPSC.LAST_ACTION_TMSTMP = CURRENT_TIMESTAMP,
              ftpsc.next_step = v1.next_step,
              ftpsc.curr_step = v1.STEP,
              ftpsc.action_script = v1.action_script
           WHERE CURRENT_TIMESTAMP >= v1.LAST_ACTION_TMSTMP + v1.WAIT_UNTIL;

COMMIT;

Я пытался сделать это, используя обычное обновление, но я получаю ORA-01732: операция манипулирования данными недопустима в этом представлении.

UPDATE (SELECT FTPSC.SESSION_ID,
                        FTPSC.ORDER_DATE,
                        FTPSC.CURR_STEP,
                        FTPSC.NEXT_STEP,
                        FTPSC.ACTION_SCRIPT,
                        sa.step,                                    --New Step
                        sa.next_step AS "NNS",                 --New Next Step
                        FTPSC.LAST_ACTION_TMSTMP,
                        SA.ACTION_SCRIPT AS "NAS",         --New action script
                        sa.ref_code,
                        SA.WAIT_UNTIL
          FROM    DSTETL.SHB_FTPS_CONTROLLER ftpsc
               LEFT JOIN
                  DSTETL.SHB_ACTIONS sa
               ON     SA.REF_CODE = FTPSC.REF_CODE
                  AND SA.STEP > ftpsc.curr_step
                  AND sa.step = ftpsc.next_step) t
   SET t.curr_step = t.step,
       t.LAST_ACTION_TMSTMP = CURRENT_TIMESTAMP,
       t.next_step = t."NNS",
       t.action_script = t."NAS";

       COMMIT;

Буду признателен за любой совет, я уже понимаю, что это потому, что в таблице Action есть несколько Ref_Codes, но REF_CODE || STEP уникален.И вывод:

SELECT DISTINCT FTPSC.SESSION_ID,
                                FTPSC.ORDER_DATE,
                                sa.step,
                                sa.next_step,
                                LAST_ACTION_TMSTMP,
                                SA.ACTION_SCRIPT,
                                sa.ref_code,
                                SA.WAIT_UNTIL
                  FROM DSTETL.SHB_FTPS_CONTROLLER ftpsc, DSTETL.SHB_ACTIONS sa
                 WHERE     SA.REF_CODE = FTPSC.REF_CODE
                       AND SA.STEP > ftpsc.curr_step
                       AND sa.step = ftpsc.next_step;

Это то, как я хочу, чтобы таблица контроллера обновлялась как.

Заранее спасибо.

1 Ответ

0 голосов
/ 27 февраля 2019

Похоже, что вы хотите сделать: обновите каждую строку в таблице Controller, указав соответствующие данные «следующего шага» из таблицы Actions.Но ваш оператор Merge дважды запрашивает таблицу Controller, что сбивает с толку.

Это то, что вы пытаетесь сделать?

MERGE INTO DSTETL.SHB_FTPS_CONTROLLER ftpsc
     USING (SELECT 
                    step,
                    next_step,
                    ACTION_SCRIPT,
                    ref_code,
                    WAIT_UNTIL
              FROM DSTETL.SHB_ACTIONS
             ) sa
        ON (sa.REF_CODE = FTPSC.REF_CODE)
WHEN MATCHED
THEN
   UPDATE SET FTPSC.LAST_ACTION_TMSTMP = CURRENT_TIMESTAMP,
              ftpsc.next_step = sa.next_step,
              ftpsc.curr_step = sa.STEP,
              ftpsc.action_script = sa.action_script
         WHERE CURRENT_TIMESTAMP >= ftpsc.LAST_ACTION_TMSTMP + sa.WAIT_UNTIL
           AND SA.STEP > ftpsc.curr_step
           AND sa.step = ftpsc.next_step;

РЕДАКТИРОВАТЬ: обновленный запрос

РЕДАКТИРОВАТЬ 2: Итак, в своем исходном запросе в разделе USING вы выбирали строки в таблице Controller, которые вы хотели обновить ... но вы никогда не соединяли эти строки с таблицей Controller из раздела MERGE INTO, чтобы сопоставить их.Наличие одного и того же псевдонима «ftpsc» лишь сделало менее ясным, что это два отдельных объекта в запросе, и какой из них вы хотите обновить.

Честно говоря, я не совсем понимаю, почему Oracle не позволяетВы обновляете столбцы, которые появляются в предложении USING..ON. Очевидно, что он отлично работает в SQL Server .

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