这是我桌子的简化版。
CREATE TABLE TBLAGENT(AGENTID NUMBER, NUMBERSENT NUMBER, AGENTNAME VARCHAR2(100));
INSERT INTO TBLAGENT VALUES(100,NULL,'KNIGHT');
INSERT INTO TBLAGENT VALUES(200,NULL,'SUPES');
INSERT INTO TBLAGENT VALUES(300,NULL,'SPIDEY');
CREATE TABLE TBLSERVICES(AGENTID NUMBER, SERVICES NUMBER);
INSERT INTO TBLSERVICES VALUES(100,44);
INSERT INTO TBLSERVICES VALUES(200,13);
INSERT INTO TBLSERVICES VALUES(300,24);
INSERT INTO TBLSERVICES VALUES(100,34);
INSERT INTO TBLSERVICES VALUES(200,13);
INSERT INTO TBLSERVICES VALUES(300,24);
SELECT TA.AGENTID, SUM(SERVICES), TA.AGENTNAME, TA.NUMBERSENT
FROM TBLAGENT TA, TBLSERVICES TS
WHERE TA.AGENTID = TS.AGENTID
GROUP BY TA.AGENTID, TA.AGENTNAME, TA.NUMBERSENT
要求是使用tblServices表中的SUM(Services)更新tblAgent表中的NUMBERSENT列。
我想出了这个更新声明。
/*Works*/
UPDATE tblagent t
SET t.numbersent =
(SELECT SUM(services)
FROM tblservices x
WHERE t.agentid = x.agentid
GROUP BY x.agentid)
当我将此语句的语法更改为INNER JOIN语法时,它会失败。
/*Throws an error*/
UPDATE tblagent t
SET t.numbersent =
(SELECT SUM(services)
FROM tblservices x INNER JOIN tblAgent t
ON t.agentid = x.agentid
GROUP BY x.agentid)
这会引发错误ORA-01427:单行子查询返回多行
为什么第二个语句会抛出错误?
答案 0 :(得分:4)
让我们看看2个查询如何更详细地工作:
首先,有效的那个:
/*Works*/
UPDATE tblagent t
SET t.numbersent =
(SELECT SUM(services)
FROM tblservices x
WHERE t.agentid = x.agentid
GROUP BY x.agentid)
显然,子查询必须返回一个值才能在SET中使用,所以让我们自己看一下:
SELECT SUM(services)
FROM tblservices x
WHERE t.agentid = x.agentid
GROUP BY x.agentid
请注意,此处的“t”别名将子查询与外部查询相关联 - 即在评估子查询时它具有一个特定值,例如
SELECT SUM(services)
FROM tblservices x
WHERE 123 = x.agentid
GROUP BY x.agentid
因此,尽管查询组的结果是x.agentid,但实际上只有一个x.agentid值,即t.agentid的当前值(例如123)。所以这很有效。
现在单独查看第二个查询的子查询:
SELECT SUM(services)
FROM tblservices x INNER JOIN tblAgent t
ON t.agentid = x.agentid
GROUP BY x.agentid
此时t.agentid 不是对外部查询的引用,因此此查询不与外部查询相关联。 可以返回超过1行(只需运行并查看),因此不能在外部查询的SET子句中安全使用。
答案 1 :(得分:3)
您是否尝试单独运行子查询以确保它只返回一行?
答案 2 :(得分:3)
@ Tony Andrews 是对的,如果你还想使用INNER JOIN,你应该这样写:
UPDATE tblagent t1
SET t1.numbersent =
(SELECT SUM(services)
FROM tblservices x INNER JOIN tblAgent t
ON t.agentid = x.agentid
GROUP BY x.agentid
having t1.agentid = x.agentid)
(要使上部和内部DML有一个公共列,以便不返回多行)
但我当然认为这只是使你的工作复杂化而已。仅使用第一个变体......这是更好的建议。
答案 3 :(得分:2)
您使用INNER JOIN重新分配t
,因此外部t
不再与UPDATE相关联。
答案 4 :(得分:1)
实际上现在我考虑一下,第一个版本是相关子查询,第二个版本不是。如果没有数据可以尝试,我无法告诉你,但这可能与它有关。
答案 5 :(得分:1)
tblAgent
中有两行具有相同的agentid
。如果没有agentid is NULL
,那么这可能会让您失望。
检查:
select * from
(
SELECT count(*) c, agentid from tblAgent group by agentid
) x
where x.c > 1
如果有任何行回来,那就是你的问题。
答案 6 :(得分:0)
不应该是
(SELECT x.agentid, SUM(services)
FROM tblservices x INNER JOIN tblAgent t
ON t.agentid = x.agentid
GROUP BY x.agentid)
如果您是通过agentid加入,或
(SELECT SUM(services)
FROM tblservices x INNER JOIN tblAgent t
ON t.agentid = x.agentid
)
如果你不是吗?