Reputation: 3
Anyone can help me correct this SQL query below? I got error that says subquery return more than 1 row. 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;
Upvotes: 0
Views: 151
Reputation: 3
thanks all. I realise my mistake. It's because there must be a primary key during the matching.
Upvotes: 0
Reputation: 4230
It looks like you are using ROWNUM
in the inner most query of your MOD(b.L_PARTKEY,2)=0
case.
The way ROWNUM works, is basically that it will get assigned to a row in a result after the WHERE
clause has been evaluated.
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.
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. That works, because the ROWNUM
has been assigned to each of the rows in that result by then.
You should consider doing the same for the first CASE
as you do for the second:
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.
Upvotes: 0
Reputation: 65228
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 ). 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.
Upvotes: 0