ORA-30926 - 合并状态

时间:2014-07-24 14:32:56

标签: oracle merge distinct

我收到ORA-30926错误。我对此进行了研究,发现这通常是由USING子句中指定的查询中的重复引起的。

问题是我最终删除了重复项并存储在一个临时表(temp_distinct)中,而我在MERGE中指的是这个表。这是我的代码片段:

MERGE INTO name_test nt 
USING (select name from temp_distinct) s 
ON (1=1)
WHEN MATCHED
THEN UPDATE SET nt.fn = s.name, nt.LN = s.name

这是我的表的结构:

NAME_TEST

FN    LN
----- -----
Ruc   Rag
Ruc   Ran
Sam   Kum
Ruc   Ran
Ruc   Kum
Ran   Dev
Rag   Agar
Rag   Ran

TEMP_DISTINCT

FN    NUMB NAME  NUM
----- ---- ----- ---
Sam   1    Mark  1
Rag   2    Steve 2
Dev   3    John  3
Kum   4    Dave  4
Ruc   5    Mich  5
Agar  6    Dean  6
Ran   7    Phil  7

因此,您可以看到USING子句中没有重复。我正在尝试替换NT.FN = S.NAMENT.LN = S.NAME

基本上我想用来自FN表的LNNAME_TEST中的名称替换TEMP_DISTINCT表中不同的名称。最终输出应如下所示:

FN     LN
------ ------
Mich   Steve
Mich   Phil
Mark   Dave
Mich   Phil
Mich   Dave
Phil   John
Steve  Dean
Steve  Ran

2 个答案:

答案 0 :(得分:1)

您的查询无法执行,因为(1 = 1) oracle无法获得一组稳定的行,要清楚检查一下:

SQL> create table ttt (name varchar2(20 char));

Table created.

SQL> insert into ttt values('first1');

1 row created.

SQL> insert into ttt values('second2');

1 row created.

SQL> merge into ttt t1 using (select 'name' name from dual) t2 on (1 = 1) when matched then update set t1.name = t2.name;

2 rows merged.

SQL> select * from ttt;

NAME
--------------------
name
name

“t2”子查询中只有一行,并且合并操作已成功完成。但是如果你的子查询得到多行,我会遇到ORA-30926:

SQL> merge into ttt t1 using (select 'name' || level name from dual connect by rownum < 4) t2 on (1 = 1) when matched then update set t1.name = t2.name;
merge into ttt t1 using (select 'name' || level name from dual connect by rownum < 4) t2 on (1 = 1) when matched then update set t1.name = t2.name
           *
ERROR at line 1:
ORA-30926: unable to get a stable set of rows in the source tables


SQL> select * from ttt;

NAME
--------------------
name
name

SQL>

Oracle不知道哪些值与行相关联。您的结果集不明确。为了能够执行此合并,您必须具有正常条件,例如:

SQL> alter table ttt add id number(10);

Table altered.

SQL> update ttt set name = 'name1', id = rownum;

2 rows updated.

SQL> select * from ttt;

NAME                         ID
-------------------- ----------
name1                         1
name1                         2

SQL> merge into ttt t1 using (select 'name' name, level id from dual connect by rownum < 4) t2 on (t1.id = t2.id) when matched then update set t1.name = t2.name;

2 rows merged.

SQL> select * from ttt;

NAME                         ID
-------------------- ----------
name                          1
name                          2

SQL>

正如您所见,“ttt”表已成功合并。

答案 1 :(得分:1)

除了来自@zaratustra的解释之外,您的合并还尝试将fnln设置为相同的name值,因此它不会给出结果你想要它甚至有效。在您尝试更新fn条款时,您无法在ln条款中使用usingname_test

如果您的fn表格中有一个主键(或至少是唯一的)列,那么您可以在合并中包含该列,但您仍然只能正确更新{{1}一次通过}或ln值。

我不确定你为什么不进行简单的更新:

update name_test nt
set fn = (select td.name from temp_distinct td where td.fn = nt.fn),
  ln = (select td.name from temp_distinct td where td.fn = nt.ln);

8 rows updated.

select * from name_test;

FN    LN  
----- -----
Mich  Steve 
Mich  Phil  
Mark  Dave  
Mich  Phil  
Mich  Dave  
Phil  John  
Steve Dean  
Steve Phil