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

введите здесь описание изображения

Я выполняю запрос на слияние для обновления 2 столбцов в таблице, но получаю следующую ошибку ORA-30926: невозможно получить стабильный набор строк в исходных таблицах.

Когда я выполняю запрос на слияние, но я уже использовал раздел и где rn=1 в предложении использования, чтобы получить только неповторяющиеся записи из источника, но Oracle все еще выдает ошибку.

Что я могу сделать, чтобы решить эту проблему?

MERGE
/*+ parallel(A) enable_parallel_dml*/
INTO
(
  SELECT
    PAY_RANGE_START_DATE_KEY,
    AA_PERSON_NATURAL_KEY,
    AA_PERSON_ASSIGNMENT_KEY,
    SCHEDULE_LINE_ID,
    SRC_CREATED_DATE,
    SRC_LAST_UPDATE_DATE
  FROM
    EDWFIN.PSP_LABOR_SCHD_DAY_F_ROLLUP
)
A USING
(
SELECT
  PAY_RANGE_START_DATE_KEY,
  AA_PERSON_NATURAL_KEY,
  AA_PERSON_ASSIGNMENT_KEY,
  SCHEDULE_LINE_ID,
  SRC_CREATED_DATE,
  SRC_LAST_UPDATE_DATE
FROM
  (
    SELECT
      PAY_RANGE_START_DATE_KEY,
      AA_PERSON_NATURAL_KEY,
      AA_PERSON_ASSIGNMENT_KEY,
      SCHEDULE_LINE_ID,
      SRC_CREATED_DATE,
      SRC_LAST_UPDATE_DATE,
      ROW_NUMBER() OVER ( PARTITION BY PAY_RANGE_START_DATE_KEY,
      AA_PERSON_NATURAL_KEY, AA_PERSON_ASSIGNMENT_KEY, SCHEDULE_LINE_ID,
      SRC_CREATED_DATE, SRC_LAST_UPDATE_DATE ORDER BY ROWNUM ) AS rn
    FROM
      EDWFIN.PSP_LABOR_SCHD_DAY_F_ROLLUP_FRS_356
  )
WHERE
  rn = 1
)
B ON
(
  A.PAY_RANGE_START_DATE_KEY = B.PAY_RANGE_START_DATE_KEY AND
  A.AA_PERSON_NATURAL_KEY    = B.AA_PERSON_NATURAL_KEY AND
  A.AA_PERSON_ASSIGNMENT_KEY = B.AA_PERSON_ASSIGNMENT_KEY AND
  A.SCHEDULE_LINE_ID         = B.SCHEDULE_LINE_ID
)
WHEN MATCHED THEN
  UPDATE
  SET
    A.SRC_CREATED_DATE     = B.SRC_CREATED_DATE,
    A.SRC_LAST_UPDATE_DATE = B.SRC_LAST_UPDATE_DATE
  WHERE
    A.SRC_CREATED_DATE      <> B.SRC_CREATED_DATE
  OR A.SRC_LAST_UPDATE_DATE <> B.SRC_LAST_UPDATE_DATE;
   COMMIT;

person karthik    schedule 15.05.2021    source источник


Ответы (1)


Я уже использовал раздел и где rn=1 в предложении using, чтобы получить только неповторяющиеся записи из источника, но Oracle все еще выдает ошибку.

Ваш

ROW_NUMBER() OVER ( PARTITION BY PAY_RANGE_START_DATE_KEY,
      AA_PERSON_NATURAL_KEY, AA_PERSON_ASSIGNMENT_KEY, SCHEDULE_LINE_ID,
      SRC_CREATED_DATE, SRC_LAST_UPDATE_DATE ORDER BY ROWNUM ) AS rn

с фильтром rn=1 удаляет дубликаты по 6 столбцам, в то время как вы используете 4 столбца в предложении ON(). Кроме того, вы используете другой фильтр для фильтрации строк для обновления.

Самый простой способ получить то, что вы хотите, — отфильтровать необходимые данные в предложении USING:

MERGE
/*+ parallel(A) enable_parallel_dml*/
INTO
(
  SELECT
    PAY_RANGE_START_DATE_KEY,
    AA_PERSON_NATURAL_KEY,
    AA_PERSON_ASSIGNMENT_KEY,
    SCHEDULE_LINE_ID,
    SRC_CREATED_DATE,
    SRC_LAST_UPDATE_DATE
  FROM
    EDWFIN.PSP_LABOR_SCHD_DAY_F_ROLLUP
)
A USING
(
SELECT
  PAY_RANGE_START_DATE_KEY,
  AA_PERSON_NATURAL_KEY,
  AA_PERSON_ASSIGNMENT_KEY,
  SCHEDULE_LINE_ID,
  SRC_CREATED_DATE,
  SRC_LAST_UPDATE_DATE
FROM
  (
    SELECT
      BB.PAY_RANGE_START_DATE_KEY,
      BB.AA_PERSON_NATURAL_KEY,
      BB.AA_PERSON_ASSIGNMENT_KEY,
      BB.SCHEDULE_LINE_ID,
      BB.SRC_CREATED_DATE,
      BB.SRC_LAST_UPDATE_DATE,
      ROW_NUMBER() OVER ( 
         PARTITION BY BB.PAY_RANGE_START_DATE_KEY,
                      BB.AA_PERSON_NATURAL_KEY, 
                      BB.AA_PERSON_ASSIGNMENT_KEY, 
                      BB.SCHEDULE_LINE_ID
         ORDER BY ROWNUM /*?*/ 
         ) AS rn
    FROM
      EDWFIN.PSP_LABOR_SCHD_DAY_F_ROLLUP_FRS_356 BB
     ,EDWFIN.PSP_LABOR_SCHD_DAY_F_ROLLUP AA
    WHERE
      AA.PAY_RANGE_START_DATE_KEY = BB.PAY_RANGE_START_DATE_KEY AND
      AA.AA_PERSON_NATURAL_KEY    = BB.AA_PERSON_NATURAL_KEY AND
      AA.AA_PERSON_ASSIGNMENT_KEY = BB.AA_PERSON_ASSIGNMENT_KEY AND
      AA.SCHEDULE_LINE_ID         = BB.SCHEDULE_LINE_ID
      AND (
          AA.SRC_CREATED_DATE     <> BB.SRC_CREATED_DATE
       OR AA.SRC_LAST_UPDATE_DATE <> BB.SRC_LAST_UPDATE_DATE
      )
  )
WHERE
  rn = 1
)
B ON
(
  A.PAY_RANGE_START_DATE_KEY = B.PAY_RANGE_START_DATE_KEY AND
  A.AA_PERSON_NATURAL_KEY    = B.AA_PERSON_NATURAL_KEY AND
  A.AA_PERSON_ASSIGNMENT_KEY = B.AA_PERSON_ASSIGNMENT_KEY AND
  A.SCHEDULE_LINE_ID         = B.SCHEDULE_LINE_ID
)
WHEN MATCHED THEN
  UPDATE
  SET
    A.SRC_CREATED_DATE     = B.SRC_CREATED_DATE,
    A.SRC_LAST_UPDATE_DATE = B.SRC_LAST_UPDATE_DATE;

Как видите, я отфильтровал строки, которые вам не нужны, в предложении USING, поэтому вам не нужно предложение WHERE в UPDATE SET, и удалил дубликаты по 4 столбцам, используемым для сопоставления.

person Sayan Malakshinov    schedule 15.05.2021
comment
запрос, который вы предложили, выполняется в течение очень долгого времени, есть ли способ его настроить, поскольку он обновляет записи 118M, используя приведенную выше логику. - person karthik; 15.05.2021
comment
Вам необходимо предоставить дополнительную информацию: план выполнения, монитор sql, таблицы ddl и статистику и т. д. - person Sayan Malakshinov; 15.05.2021
comment
Я добавил план выполнения только для использования предложения , так как его одно только выполнение занимает более 2 часов, и оно еще не завершено. - person karthik; 15.05.2021
comment
Хорошо, во-первых, замените order by rownum только на order by null, это удалит лишнюю операцию couny. Во-вторых, вам нужно собрать статистику для обеих таблиц, так как ваш план объяснения показывает 1 строку. - person Sayan Malakshinov; 15.05.2021
comment
Я заменил порядок на ноль и собрал статистику по обеим таблицам. Последний план объяснения прилагается. - person karthik; 15.05.2021
comment
Хорошо, понятно... 22 млн строк и 1,2 млрд строк... Попробуйте добавить параллельную подсказку для этого select и проверьте, как долго это работает. Затем добавьте aa.rowid as rid во внутреннее представление в предложении using и rid в основной выбор верхнего уровня предложения using и замените on() на on(a.rowid=b.rid) и проверьте полученный план его выполнения. - person Sayan Malakshinov; 15.05.2021
comment
@ Саян Малакшинов Я добавил план объяснения после добавления параллельных подсказок, однако я не могу добавить идентификатор строки в соответствии с тем, что вы упомянули, он выдает следующую ошибку, не может выбрать ROWID или образец, представление соединения без ключа- сохраненный стол - person karthik; 15.05.2021
comment
Как я уже говорил ранее, aa.rowid as rid должен быть во внутреннем представлении, а не на верхнем уровне выбора. На верхнем уровне select должен быть rid - person Sayan Malakshinov; 15.05.2021
comment
Давайте продолжим это обсуждение в чате. - person karthik; 15.05.2021
comment
есть ли другой альтернативный способ упростить запрос? например, используя max () - person karthik; 15.05.2021
comment
Я сказал заменить все предложение on(...) на on(a.rowid=b.rid), вам не нужны предыдущие 4 условия, поскольку они уже были отфильтрованы в предложении использования - person Sayan Malakshinov; 15.05.2021
comment
А если честно, то это уже другой вопрос и нужно создать еще одну тему по оптимизации запросов - person Sayan Malakshinov; 15.05.2021