2011-10-14 163 views
0

我以前問過這個問題,但我沒有得到任何幫助。 我想獲得給定屬性的兩個不同表中的行數。 這是我的代碼。 相反抓取,此時的條件成立的總計數,我收到表PLSQL ORACLE COUNT

create or replace PROCEDURE p1(suburb IN varchar2) 
    as 
     person_count NUMBER; 
     property_count NUMBER; 
    BEGIN 
     SELECT count(*) INTO person_count 
     FROM person p WHERE p.suburb = suburb ; 

     SELECT count(*) INTO property_count 
     FROM property pp WHERE pp.suburb = suburb ; 


     dbms_output.put_line('Number of People :'|| person_count); 
     dbms_output.put_line('Number of property :'|| property_count); 

    END; 
    /

整個計數是否有任何其他方式做到這一點,這樣我可以在郊區檢索人民的真正總數

從Person表

 PEID FIRSTNAME  LASTNAME 
    ---------- -------------------- -------------------- 
    STREET     SUBURB   POST TELEPHONE 
    ---------------------------------------- -------------------- ---- ------------ 
     30 Robert  Williams 
    1/326 Coogee Bay Rd.    Coogee   2034 9665-0211 

     32 Lily   Roy 
    66 Alison Rd.     Randwick   2031 9398-0605 

     34 Jack   Hilfgott 
    17 Flood St.     Bondi   2026 9387-0573 

從屬性表中的一些數據有些DATAS

  PNO STREET     SUBURB  POST 
    ---------- ---------------------------------------- -------------------- ---- 
    FIRST_LIS TYPE    PEID 
    --------- -------------------- ---------- 
     48 66 Alison Rd.    Randwick   2031 
    12-MAR-11 Commercial   8 

     49 1420 Arden St.    Clovelly   2031 
    27-JUN-10 Commercial    82 

     50 340 Beach St.    Clovelly   2031 
    05-MAY-11 Commercial    38 

對不起,表正在尋找。

這是我運行上述腳本時獲得的值。

 SQL> exec p1('Randwick') 
    Number of People :50 
    Number of property :33 

我改變了PROCEDURE,這就是我得到的。

SQL> create or replace PROCEDURE p1(location varchar2) 
    IS 
     person_count NUMBER; 
     property_count NUMBER; 
    BEGIN 
     SELECT count(p.peid) INTO person_count 
     FROM person p WHERE p.suburb = location ; 

     SELECT count(pp.pno) INTO property_count 
     FROM property pp WHERE pp.suburb = location ; 


     dbms_output.put_line('Number of People :'|| person_count); 
     dbms_output.put_line('Number of property :'|| property_count); 

    END; 
    /
     2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 
    Procedure created. 

    SQL> exec p1('KINGSFORD') 
    Number of People :0 
    Number of property :0 

    PL/SQL procedure successfully completed. 

    SQL> 


    SQL> 
    SQL> exec p1('Randwick') 
    Number of People :0 
    Number of property :0 

    PL/SQL procedure successfully completed. 

    SQL> 

假設是這個

SQL> exec p1('randwick'); 
    Number of People: 7 
    Number of Property: 2 
+1

請顯示2表中的一些數據和參數'郊區的值 – Yahia

+0

您最後兩個示例不同。倒數第二位表示您提供'Randwick',最後一位提示您提供'randwick'(用小寫「r」)。你的問題可能與你如何存儲你的郊區價值以及你的參數是如何傳遞給它有關。您必須將其標準化以確保匹配成功。 – Ollie

回答

7

您指定的變量相同領域的解決方案。在查詢中,suburb首先在查詢範圍內查找,並且它與suburb字段匹配,即使它不使用pp表別名。

所以,你實際上是將該字段與自己進行比較,因此獲取所有記錄(其中suburb不是NULL,即)。程序參數根本不在查詢中使用。

解決方案:更改過程參數的名稱。

爲了避免這樣的錯誤,我總是使用P_作爲過程/函數參數的前綴,並且使用V_作爲局部變量的前綴。這樣,他們就不會與字段名稱混在一起。

+0

如果我將郊區更改爲vsuburb,我會得到0作爲總計數。 – shakur007

+0

然後,在vsuburb中傳遞的值也不正確。請注意,搜索區分大小寫。必須有完全匹配。如果有疑問,請修改您的問題並添加新程序以及調用它的代碼(包括傳遞的值)。 – GolezTrol

+0

我看到你的編輯,我想我知道(或'a')問題:如果你使用'count(pp.pno)','pp.pno'不能爲NULL,否則'count'返回0.改變它到'*'或者像'1'或者''x''這樣的常量值,除非你想只計算其值不爲空的記錄。 – GolezTrol

0

首先,對於不區分大小寫的搜索創建指數:

CREATE INDEX idx_person_suburb_u ON person(upper(suburb)) 
/
CREATE INDEX idx_property_suburb_u ON property(upper(suburb)) 
/

二,使用前綴過程參數和局部變量:

CREATE OR REPLACE PROCEDURE p1(p_location VARCHAR2) 
IS 
    v_person_count NUMBER; 
    v_property_count NUMBER; 
    v_location  VARCHAR2(32767); 
BEGIN 
    IF p_location IS NOT NULL THEN 
     v_location := upper(p_location); 
     SELECT count(*) INTO v_person_count 
     FROM person WHERE upper(suburb) = v_location ; 

     SELECT count(*) INTO v_property_count 
     FROM property WHERE upper(suburb) = v_location ; 
    ELSE 
     SELECT count(*) INTO v_person_count 
     FROM person WHERE upper(suburb) IS NULL; 

     SELECT count(*) INTO v_property_count 
     FROM property WHERE upper(suburb) IS NULL;   
    END IF; 
    dbms_output.put_line('Number of People :' || v_person_count); 
    dbms_output.put_line('Number of Property :' || v_property_count); 
END; 
/
+1

count(1)和count(*)是相同的:http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:1156159920245 – vemcaster

1

雖然我同意,這個問題的原因是SQL和PL/SQL之間的命名空間問題,因爲SQL引擎已經「捕獲」了PL/SQL變量的名稱,我不認爲改變參數的名稱是最好的方法。如果你這樣做,那麼你就迫使每個開發人員開始在每個參數名稱前添加「p_」或其他一些無用的附錄,並確保它們從不創建帶有P_前綴的列。

如果您仔細查看PL/SQL提供的軟件包文檔,您會發現很少有(如果有的話)Oracle自己執行此操作的情況,儘管他們過去做了令人惱怒的不一致事情,如將table_name稱爲「tabname」。

一個更可靠的方法是在SQL語句中引用它時的前綴與PL/SQL程序名變量名:

SELECT count(*) 
INTO person_count 
FROM person p WHERE p.suburb = p1.suburb ; 

在你的情況你清楚不命名您的程序「P1」,所以其實你有這樣的:

SELECT count(*) 
INTO person_count 
FROM person p WHERE p.suburb = count_suburb_objects.suburb ; 

你的代碼現在免疫的變量名捕獲 - 作爲獎勵你的文本編輯器可能在哪些方面你已經在SQL語句中使用一個變量名的所有實例當你雙擊過程名稱。

+0

+1此方法也適用於可以幫助您在嵌套過程時識別變量的範圍。 –