2010-11-08 21 views
0

下面是我的表格的簡化版本。爲什麼更新不適用於內部連接?

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:單行子查詢返回多行

爲什麼第二條語句拋出一個錯誤嗎?

回答

3

@託尼·安德魯斯是正確的,如果你仍然想使用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

您是否嘗試單獨運行子查詢以確保它只返回一行?

+0

+1。這是一個非常明顯的錯誤消息......子查詢需要返回一行,並且它返回多個。 – ceejayoz 2010-11-08 22:14:01

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 
    ) 

,如果你不?

+0

否。子查詢應該只返回SUM(服務)。 – abhi 2010-11-08 22:14:51

+0

...這是第二個子查詢所做的。 – SteveCav 2010-11-08 22:57:37

1

其實現在我想到了,第一個版本是一個相關的子查詢,第二個版本不是。沒有數據去嘗試,我無法告訴你,但這可能與它有關。

2

您使用INNER JOIN重新分配t,因此外部t不再鏈接到UPDATE。

+0

是的,tblAgent表有兩個不相關的用途。 – 2010-11-08 22:45:53

1

您有兩行tblAgentagentid相同。如果沒有agentid is NULL,這可能已經逃脫了您的注意。

檢查:

select * from 
(
    SELECT count(*) c, agentid from tblAgent group by agentid 
) x 
where x.c > 1 

如果任何行回來,那是你的問題。

4

讓我們來看看2個查詢更詳細的工作原理:

首先,其工作方式之一:

/*Works*/ 
UPDATE tblagent t 
    SET t.numbersent = 
     (SELECT SUM(services) 
      FROM tblservices x 
     WHERE t.agentid = x.agentid 
     GROUP BY x.agentid) 

顯然,子查詢必須返回一個值的集中使用,讓我們看看那個對自己:

 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子句中使用。