为什么更新不能与内部联接一起使用?
这是我的表格的简化版本。
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:单行子查询返回多于一行
为什么第二个语句会引发错误?
Here's a simplified version of my table.
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
The requirement is to update the NUMBERSENT column in the tblAgent table with the SUM(Services) from tblServices table.
I came up with this update statement.
/*Works*/
UPDATE tblagent t
SET t.numbersent =
(SELECT SUM(services)
FROM tblservices x
WHERE t.agentid = x.agentid
GROUP BY x.agentid)
When I change the syntax of this statement to INNER JOIN syntax, it fails.
/*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)
This throws up an error ORA-01427: single-row subquery returns more than one row
Why would the second statement throw an error?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
让我们更详细地看看这 2 个查询是如何工作的:
首先,有效的一个:
显然子查询必须返回一个值以在 SET 中使用,所以让我们单独看看它:
注意这里的“t”别名将子查询与外部查询相关联 - 即,当评估子查询时,它具有一个特定值,例如
因此,尽管查询按 x.agentid 对结果进行分组,但实际上只有一个 x.agentid 值,即 t.agentid 的当前值(例如123)。所以这有效。
现在看看第二个查询的子查询:
这次 t.agentid 不是对外部查询的引用,因此该查询与外部查询不相关。它可以返回多于1行(只需运行它并查看),因此不能在外部查询的SET子句中安全使用。
Let's look at how the 2 queries work in more detail:
First, the one that works:
Clearly the subquery must return a single value to use in the SET, so let's look at that on its own:
Note that the "t" alias here correlates the subquery to the outer query - i.e. it has one specific value when the subquery is evaluated e.g.
Therefore, although the query groups results by x.agentid, there is only in fact one x.agentid value i.e. the current value of t.agentid (e.g. 123). So this works.
Now look at the second query's subquery on its own:
This time t.agentid is not a reference to the outer query, so this query is not correlated to the outer query. It can return more than 1 row (just run it and see), and thus cannot be safely used in the SET clause of the outer query.
@Tony Andrews 是对的,如果你仍然想使用 INNER JOIN 你应该这样写:(
为了让上部和内部 DML 有一个公共列,不要返回多于一行)
但是当然我认为这只是使你的工作复杂化,仅此而已......使用第一个变体......这是更好的建议。
@Tony Andrews is right and if you still want to use INNER JOIN you should write this:
(To have upper and inner DML one common column,for not to return more than one row)
But of course I think this is just complicating your job and nothing more..Use the first variant...This is better Advice.
您是否尝试单独运行子查询以确保它只返回一行?
Did you try running the subquery by itself to make sure it only returns one row?
您使用 INNER JOIN 重新分配
t
,因此外部t
不再链接到 UPDATE。You reassign
t
with the INNER JOIN, so the outert
is not linked to the UPDATE any more.实际上现在我想起来,第一个版本是相关子查询,第二个版本不是。没有数据可以尝试,我无法告诉你,但这可能与它有关。
Actually now that I think about it, the first version is a correlated subquery, the second one is not. Without data to try it with I couldn't tell you but that probably has something to do with it.
tblAgent
中有两行具有相同的agentid
。如果没有agentid 为 NULL
的情况,您可能不会注意到这一点。检查:
如果有任何行返回,那就是你的问题。
You have two rows in
tblAgent
with the sameagentid
. This might have escaped your notice if there are no whereagentid is NULL
.To check:
If any rows come back, that's your problem.
加入,不应该是这样吗?
如果您是通过agentid 加入,或者
不是通过agentid
Shouldn't that be
if you're joining by agentid, or
if you're not?