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
时,您是在尝试在分配之前对其进行比较。
在另一个CASE
和MOD(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: 单行子查询返回多于一行