2016-11-07 2 views
0

Я пытаюсь выполнить слияние в таблицу (назовем ее table1) с table2. В состоянии USING мне нужна третья таблица (table3). Эта третья таблица содержит некоторые идентификаторы, которые мне нужны в table1. Упрощенная версия моего слияния выглядит следующим образом:не удалось получить стабильный набор строк error

MERGE INTO table1 a 
        USING (
         SELECT ID, address 
         FROM table3 b 
          Where address IN 
          (
           SELECT address 
           FROM table3 
           WHERE address IS NOT NULL 
            AND ID> 0 
           GROUP BY address 
           HAVING COUNT(*) = 1 
          ) 
        ) c 
        ON (a.address = c.address) 
        WHEN MATCHED THEN 
         UPDATE SET a.ID = c.ID 
         WHERE a.ID = 0 

Я знаю, что ошибка я получаю обычно вызывается запрос в ПРИМЕНЕНИИ статьи, но теоретически эта проблема должна быть устранена путем подсчета (*) = 1 условие , У меня есть дубликаты в table2, но все они должны получить ID от table3 или ID 0, если адрес дублируется в table3. Идентификаторы уникальны для адреса, поэтому они должны быть разными.

P.S. Это слияние выполняется автоматически сценарием, поэтому я могу изменить запрос, чтобы добавить дополнительные условия/ограничения, но я не могу изменить структуру [это означает, что я должен использовать эти 3 таблицы, как они есть).

Надеюсь, это имеет смысл. Любые идеи, почему это все еще не работает для меня?

+0

Вы говорите, что вы не включили часть, относящуюся к таблице2, однако ошибка связана с этим. Обновите свой примерный запрос, чтобы включить его, а также некоторые примерные данные ввода для всех трех таблиц. Может быть, все, что вам нужно, является отличным, но мы пока не можем сказать. – Boneist

+0

@Boneist, моя ошибка там. Я забыл отредактировать эту часть. c относится к выбору в таблице 3. псевдоним отображается в запросе. – AnnaB

+0

Может ли отдельный идентификатор помочь, если у меня есть условие count (*) = 1? Как я уже говорил, идентификаторы не повторяются, они уникальны. Итак, если мое мышление верное, это не должно быть проблемой. – AnnaB

ответ

0

Попробуйте это:

MERGE INTO table1 a 
        USING (
         SELECT max(ID), address 
          FROM table3 b 
          WHERE address IS NOT NULL AND ID > 0 
          GROUP BY address 
          HAVING COUNT(*) = 1     
        ) c 
        ON (a.address = c.address) 
        WHEN MATCHED THEN 
         UPDATE SET a.ID = c.ID 
         WHERE a.ID = 0; 

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

MERGE INTO table1 a 
        USING (
         SELECT ID, address 
         FROM table3 b 
          AND address IN 
          (
           SELECT address 
           FROM table3 
           WHERE address IS NOT NULL 
            AND ID> 0 
           GROUP BY address 
           HAVING COUNT(*) = 1 
          ) 
          WHERE address IS NOT NULL 
            AND ID> 0 
        ) c 
        ON (a.address = c.address) 
        WHEN MATCHED THEN 
         UPDATE SET a.ID = c.ID 
         WHERE a.ID = 0 
0

Эта проблема более чем вероятно из-за повторяющихся строк из таблицы2. Вот простой тест демонстрирует вопрос:

Установка:

CREATE TABLE t1 (ID INTEGER PRIMARY KEY, 
       val VARCHAR2(1)); 

CREATE TABLE t2 (ID INTEGER, 
       val VARCHAR2(1)); 

INSERT INTO t1 (ID, val) VALUES (1, 'A'); 

INSERT INTO t2 (ID, val) VALUES (1, 'B'); 
INSERT INTO t2 (ID, val) VALUES (1, 'B'); 

COMMIT; 

Merge, что будет ошибка:

MERGE INTO t1 USING t2 
    ON (t1.id = t2.id) 
WHEN MATCHED THEN 
    UPDATE SET t1.val = t2.val; 

ORA-30926: unable to get a stable set of rows in the source tables

Merge, что получится:

MERGE INTO t1 USING (SELECT DISTINCT id, val FROM t2) t2 
    ON (t1.id = t2.id) 
WHEN MATCHED THEN 
    UPDATE SET t1.val = t2.val; 

N.B. Второе слияние будет по-прежнему терпеть неудачу, если у вас есть разные значения, возвращаемые для val для одного и того же идентификатора; это означает, что у вас будет несколько строк, возвращаемых для данного идентификатора, и Oracle не будет знать, какой из них использовать для обновления целевой таблицы.

Чтобы убедиться, что ваш оператор слияния будет работать, вам необходимо убедиться, что вы вернете не более 1 строки на адрес в исходном подзапросе.

+0

Я всегда думал, что он обновит все мои строки. Скажем, у меня есть адрес 123 Willow St (который дважды появляется в таблице, которую я пытаюсь объединить) с идентификатором 5 в таблице, содержащей ID. Я ожидал, что он поместит id 5 в мой адрес, как только он увидит этот адрес. Но спасибо за это. Однако просто поместить 'отдельный идентификатор 'в мой запрос не решит мою проблему. Я что-то толстый и что-то забываю? – AnnaB

+0

Вы должны решить, что хотите. Скажите, что у вас есть строка 123 Willow Street в вашей целевой таблице (таблица1) и две строки с идентификаторами 1 и 2 для одного и того же адреса в исходном запросе - что вы ожидаете, что идентификатор целевой таблицы закончится? 1 или 2? И какова была логика выбора? После этого вы сможете реплицировать эту логику в исходном запросе - например, возможно, вы выбираете самый низкий идентификатор, или, может быть, вы выбираете самый большой, а это значит, что вы после запроса min/max. Или, возможно, вы идете об этом не так; чего вы пытаетесь достичь? – Boneist

+0

Думаю, мне нужно вдаваться в подробности, которые, как я думал. Итак, здесь идет ... 'table3', скажем, содержит список всех адресов в графстве и их соответствующий ID. Таким образом, здесь вы можете иметь один и тот же адрес дважды с двумя отдельными идентификаторами ТОЛЬКО, если они находятся в разных городах или районах. Ни один город не имеет одного и того же адреса дважды, не так ли? Точный же адрес не будет содержать 2 разных идентификатора. И если у меня есть тот же адрес дважды, с двумя разными идентификаторами, я исключаю эти случаи с count (*) = 1. В таблице, в которую я сливаюсь, 'table1' будет содержаться идентификаторы, адреса и дополнительная информация. – AnnaB

Смежные вопросы