简体   繁体   English

SQL错误ORA 01427-子查询返回更新语句导致的多于1行

[英]SQL error ORA 01427 - Subquery returns more than 1 row resulted from update statement

Anyone can help me correct this SQL query below? 任何人都可以帮助我更正以下此SQL查询吗? I got error that says subquery return more than 1 row. 我收到错误消息说子查询返回多于1行。 Thanks. 谢谢。

UPDATE LINEITEM a
SET a.l_manufacturer_name=(with NAMES as (SELECT CASE
    WHEN MOD(b.L_PARTKEY,2)=0 THEN (SELECT M_NAME FROM MANUFACTURER m WHERE ROWNUM=1)
    WHEN MOD(b.L_PARTKEY,2)=1 THEN (SELECT M_NAME FROM (SELECT M_NAME, ROWNUM AS MYROW FROM (SELECT M_NAME, ROWNUM FROM MANUFACTURER m)) WHERE MYROW=2)
END AS MANUFACTURER_NAME FROM LINEITEM b)
SELECT MANUFACTURER_NAME FROM NAMES N WHERE N.L_PARTKEY=A.L_PARTKEY;

Actually, the error message is obvious( Too_Many_Rows exception raised due to the returning results for at least one select statement has more than one row ). 实际上,错误消息是显而易见的( 由于至少一个select语句的返回结果具有多于一行而引发Too_Many_Rows异常 )。 In such cases an aggregate function may help us depending on our situation : 在这种情况下,汇总函数可能会根据我们的情况为我们提供帮助:

SQL> CREATE TABLE MANUFACTURER(M_NAME varchar2(75));
SQL> CREATE TABLE LINEITEM(l_manufacturer_name varchar2(75),l_partkey int);

SQL> INSERT INTO MANUFACTURER VALUES('abc');
SQL> INSERT INTO MANUFACTURER VALUES('def');
SQL> INSERT INTO LINEITEM VALUES('abc',1);
SQL> INSERT INTO LINEITEM VALUES('def',2);
SQL> INSERT INTO LINEITEM VALUES('abc',1);
SQL> INSERT INTO LINEITEM VALUES('def',2);

SQL> UPDATE LINEITEM a
   SET a.l_manufacturer_name =
       (SELECT CASE
                 WHEN MOD(b.L_PARTKEY, 2) = 0 THEN
                  (SELECT M_NAME FROM MANUFACTURER m WHERE ROWNUM = 1)
                 WHEN MOD(b.L_PARTKEY, 2) = 1 THEN
                  (SELECT M_NAME
                     FROM (SELECT M_NAME, ROWNUM AS MYROW
                             FROM (SELECT M_NAME, ROWNUM FROM MANUFACTURER m))
                    WHERE MYROW = 2)
               END AS MANUFACTURER_NAME
          FROM LINEITEM b
         WHERE a.l_partkey = b.l_partkey);


ORA-01427: single-row subquery returns more than one row 


SQL> UPDATE LINEITEM a
   SET a.l_manufacturer_name =
       (SELECT CASE
                 WHEN MOD(max(b.L_PARTKEY), 2) = 0 THEN
                  (SELECT M_NAME FROM MANUFACTURER m WHERE ROWNUM = 1)
                 WHEN MOD(max(b.L_PARTKEY), 2) = 1 THEN
                  (SELECT M_NAME
                     FROM (SELECT M_NAME, ROWNUM AS MYROW
                             FROM (SELECT M_NAME, ROWNUM FROM MANUFACTURER m))
                    WHERE MYROW = 2)
               END AS MANUFACTURER_NAME
          FROM LINEITEM b
         WHERE a.l_partkey = b.l_partkey
         GROUP BY b.L_PARTKEY );

4 row updated.

It looks like you are using ROWNUM in the inner most query of your MOD(b.L_PARTKEY,2)=0 case. 看起来您在MOD(b.L_PARTKEY,2)=0情况的最内层查询中使用的是ROWNUM

The way ROWNUM works, is basically that it will get assigned to a row in a result after the WHERE clause has been evaluated. ROWNUM的工作方式基本上是在评估WHERE子句后将其分配给结果中的一行。

This means that when you are refering to ROWNUM=1 in the WHERE clause, you are trying to compare it before it has been assigned. 这意味着当您在WHERE子句中引用ROWNUM=1时,您尝试在分配它之前进行比较。

In the other CASE with MOD(b.L_PARTKEY,2)=1 you have an inner select that returns a ROWNUM , you then refer to it with MYROW=2 outside that inner query. 在其它CASEMOD(b.L_PARTKEY,2)=1你具有内选择一个返回ROWNUM ,则然后参照其与MYROW=2即内部查询之外。 That works, because the ROWNUM has been assigned to each of the rows in that result by then. 那行得通,因为那时ROWNUM已分配给该结果中的每一行。

You should consider doing the same for the first CASE as you do for the second: 您应该考虑对第一个CASE进行与对第二个CASE相同的操作:

UPDATE LINEITEM a 
  SET a.l_manufacturer_name = (
    SELECT
      CASE 
        WHEN MOD(b.L_PARTKEY,2)=0 
          THEN (
            SELECT
              M_NAME 
            FROM (
              SELECT 
                M_NAME, 
                ROWNUM AS MYROW 
              FROM (
                SELECT 
                  M_NAME, 
                  ROWNUM 
                FROM MANUFACTURER m
              )
            ) 
            WHERE 
              MYROW=1) 
        WHEN MOD(b.L_PARTKEY,2)=1 
          THEN (
            SELECT
              M_NAME 
            FROM (
              SELECT 
                M_NAME, 
                ROWNUM AS MYROW 
              FROM (
                SELECT 
                  M_NAME, 
                  ROWNUM 
                FROM MANUFACTURER m
              )
            ) 
            WHERE 
              MYROW=2) 
      END AS MANUFACTURER_NAME 
    FROM LINEITEM b 
    WHERE 
      a.l_partkey=b.l_partkey);

This should ensure that only one row is returned from either case, and your assignment should work. 这应该确保任一情况下仅返回一行,并且您的分配应该起作用。

thanks all. 谢谢大家 I realise my mistake. 我意识到我的错误。 It's because there must be a primary key during the matching. 这是因为匹配期间必须有一个主键。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM