Как избежать ORA-01427 в обновлении заявления? - PullRequest
0 голосов
/ 02 июля 2018

Я знаю, что подзапрос должен возвращать 1 строку. Можете ли вы дать мне знать, как изменить запрос UPDATE ниже, чтобы обновить таблицу test1 со строками таблицы сопоставления?

update test1 a set daily_value = ( select daily_value from mapping b where a.table_name = b.table_name);
                              *
ERROR at line 1:
ORA-01427: single-row subquery returns more than one row


create table test1
( table_name varchar2(10),
  daily_value varchar2(10)
)
/

insert into test1(table_name) values ('first');
insert into test1(table_name) values ('first');
commit;


create table mapping
( table_name varchar2(10),
  daily_value varchar2(10)
)
/

insert into mapping values ('first','value_1');
insert into mapping values ('first','value_2');
commit;



TEST1 table should have below data

TABLE_NAME  DAILY_VALUE
FIRST       value_1
FIRST       value_2

Ответы [ 3 ]

0 голосов
/ 02 июля 2018

Один из вариантов - выбрать MIN или MAX из (daily_value)

UPDATE test1 a
SET
    daily_value = (
        SELECT
            MIN(daily_value)
        FROM
            mapping b
        WHERE
            a.table_name = b.table_name
    );

Но это сделает ваши данные в test1 такими:

TABLE_NAME  DAILY_VALUE
first   value_1
first   value_1

Если вы не хотите этого, вы должны добавить еще один уникальный столбец, который относится к двум таблицам, кроме table_name

Демо

0 голосов
/ 02 июля 2018

Вам нужно определиться с критериями упорядочения в ваших таблицах, чтобы решить, какие строки получают value_1, а какие - value_2. Если у вас нет заказа, простой rownum может работать; например:

merge into test1 t1
using( select daily_value, table_name, rownum as rn 
       from mapping
     ) M
on (M.table_name = t1.table_name and rownum = M.rn)     
when matched then 
    update set daily_value = M.daily_value    

дает:

TABLE_NAME DAILY_VALUE
---------- -----------
first      value_1    
first      value_2
0 голосов
/ 02 июля 2018

Обновление не может вернуть 1 строку, так как не может различить обе строки в таблице test1, поскольку они имеют одинаковое значение «first». Если вы измените данные на другие значения, они будут работать как положено:

DELETE FROM mapping;
DELETE FROM test1;

INSERT INTO test1(table_name) VALUES ('first');
INSERT INTO test1(table_name) VALUES ('second');

INSERT INTO mapping VALUES ('first','value_1');
INSERT INTO mapping VALUES ('second','value_2');

update test1 a set daily_value = ( select daily_value from mapping b where a.table_name = b.table_name);
2 rows updated.

Лично я предпочитаю выражение MERGE, хотя, как мне кажется, немного понятнее:

MERGE INTO test1 USING mapping 
   ON (test1.table_name = mapping.table_name)
 WHEN MATCHED THEN UPDATE SET 
      test1.daily_value = mapping.daily_value; 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...