代码之家  ›  专栏  ›  技术社区  ›  Sigularity

如何在update语句中避免ora-01427?

  •  0
  • Sigularity  · 技术社区  · 8 年前

    我知道下面的子查询应该返回1行。 您能告诉我如何将下面的更新查询更改为用映射表的行更新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 回复  |  直到 8 年前
        1
  •  2
  •   Aleksej    8 年前

    您需要决定表的排序条件,以决定哪些行得到 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
    
        2
  •  0
  •   wolφi    8 年前

    更新不能返回1行,因为它不能区分表中的两行 test1 因为他们有相同的价值“第一”。如果将数据更改为具有不同的值,它将按预期工作:

    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; 
    
        3
  •  0
  •   Kaushik Nayak    8 年前

    一种选择是 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