SQL 错误 ORA 01427 - 子查询返回超过 1 行的更新语句

Posted

技术标签:

【中文标题】SQL 错误 ORA 01427 - 子查询返回超过 1 行的更新语句【英文标题】:SQL error ORA 01427 - Subquery returns more than 1 row resulted from update statement 【发布时间】:2018-04-23 20:18:15 【问题描述】:

谁能帮我纠正下面的这个 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;

【问题讨论】:

主要问题是:你想达到什么目的?使用rownum,您可以选择任意选择的行。 (例如,您告诉 DBMS:从 manufacturer 表中选择您碰巧首先读取的记录,该记录可以是表中的任何记录。)您为每个 lineitem 记录选择这样的随机 manufacturer 记录。然后从所有这些随机记录中,您尝试准确地选择一个匹配的l_partkey(您甚至没有选择)。我建议您打开另一个请求,告诉我们您要做什么(使用示例数据和预期结果)。 【参考方案1】:

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

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.

【讨论】:

【参考方案2】:

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

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

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

在另一个CASEMOD(b.L_PARTKEY,2)=1 中,您有一个返回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);

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

【讨论】:

谢谢。但是查询似乎永远加载并且无法完成。不确定因为数据库包含 1.8m 或其他原因。所以我中止了这个操作。【参考方案3】:

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

【讨论】:

以上是关于SQL 错误 ORA 01427 - 子查询返回超过 1 行的更新语句的主要内容,如果未能解决你的问题,请参考以下文章

得到以下错误 ORA-01427: 单行子查询返回多于一行 01427. 00000 - “单行子查询返回多于一行”

ORA-01427:单行子查询返回多个行

ORA-01427: 单行子查询返回多行更新

我得到那个错误 ORA-01427: 单行子查询返回多于一行

Oracle APEX 交互式报告中的错误 - ORA-01427:单行子查询返回多于一行

ORA-01427 单行子查询返回多行 - 如何解决?