0

任何人都可以帮我更正下面的这个 SQL 查询吗?我得到一个错误,说子查询返回超过 1 行。谢谢。

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;
4

3 回答 3

0

实际上,错误消息很明显(由于至少一个 select 语句的返回结果超过一行而引发了 Too_Many_Rows 异常)。在这种情况下,聚合函数可能会根据我们的情况对我们有所帮助:

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.
于 2018-04-23T20:36:09.087 回答
0

看起来您正在使用案例ROWNUM的最内部查询MOD(b.L_PARTKEY,2)=0

WHEREROWNUM 的工作方式基本上是在评估子句后将其分配给结果中的一行。

这意味着当您ROWNUM=1WHERE子句中引用时,您会尝试在分配之前对其进行比较。

另一方面CASEMOD(b.L_PARTKEY,2)=1您有一个返回 a 的内部选择,然后您在该内部查询之外ROWNUM引用它。MYROW=2那行得通,因为到那时ROWNUM已经将 分配给该结果中的每一行。

您应该考虑对第一个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);

这应该确保从任何一种情况都只返回一行,并且您的分配应该有效。

于 2018-04-23T20:37:07.357 回答
0

谢谢大家。我意识到我的错误。这是因为在匹配过程中必须有一个主键。

于 2018-05-06T21:06:49.047 回答