如何避免在更新语句中出现ORA-01427?

时间:2018-07-02 07:46:26

标签: sql oracle sql-update subquery

我知道下面的子查询应该返回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 :(得分:2)

您需要确定表的排序标准,以确定哪些行获得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

答案 1 :(得分:0)

该更新无法返回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; 

答案 2 :(得分:0)

一个选项是选择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以外的两个表之间存在关联

Demo