2013-10-17 37 views
0

我需要從這個PL/SQL塊中調用存儲函數findtotalcarmodels。這段代碼的寫法並不是我在生產中做的方式,但它是一種'橫向'思維的練習。從明確的光標調用函數

SET SERVEROUTPUT ON FORMAT WRAP SIZE 12000 
Declare 
v_model VARCHAR2(40); 
v_cost NUMBER; 
v_reg VARCHAR2(10); 
v_carcategory VARCHAR2(40); 
v_totalcars NUMBER; 
v_count DATE; 
v_maxcount DATE; 
v_maxdept VARCHAR2(20); 
cursor carcur IS 
SELECT * FROM i_car; 
v_car carcur%ROWTYPE; 
Cursor c_date (p_reg i_booking.registration%TYPE) IS 
SELECT date_reserved 
FROM i_booking 
WHERE registration = p_reg; 
v_date c_date%ROWTYPE; 
Begin 
v_totalcars := findtotalcarmodels(); 
FOR v_car IN carcur LOOP 
If v_cost <=50000 THEN v_carcategory := 'Budget Car'; 
End IF; 
If v_cost BETWEEN 50000 AND 100000 THEN v_carcategory := 'Standard Car'; 
End IF; 
If v_cost >100000 THEN v_carcategory := 'Premium Car'; 
End If; 
FOR v_date IN c_date(v_car.registration) LOOP 
v_count := v_count + 1; 
END LOOP; 
IF v_count > v_maxcount THEN 
v_maxcount := v_count; 
v_maxdept := v_car.registration; 
END IF; 
DBMS_OUTPUT.PUT_LINE('Registration:'|| ' '|| v_car.registration); 
DBMS_OUTPUT.PUT_LINE('Cost:'|| '$' ||v_car.Cost); 
DBMS_OUTPUT.PUT_LINE('Model Name:'|| ' '||v_car.model_name); 
DBMS_OUTPUT.PUT_LINE('Car Category:'|| ' '||v_carcategory); 
DBMS_OUTPUT.PUT_LINE('Total number of Cars:'|| ' '||v_totalcars); 
DBMS_OUTPUT.PUT_LINE('Most Recent Rental Date: '|| ' '||v_maxcount); 
DBMS_OUTPUT.NEW_LINE; 
END LOOP; 
END; 

我收到錯誤:

v_totalcars := findtotalcarmodels(); 
       * 
ERROR at line 19: 
ORA-06550: line 19, column 16: 
PLS-00306: wrong number or types of arguments in call to 'FINDTOTALCARMODELS' 
ORA-06550: line 19, column 1: 
PL/SQL: Statement ignored 

我是不是正確調用我的函數在正確的位置?

這是函數:

CREATE OR REPLACE Function findtotalcarmodels 
(model_name_in IN varchar2) 
RETURN NUMBER 
IS 
counter INTEGER := 0; 
CURSOR car_count_cur IS 
SELECT model_name FROM i_car WHERE model_name = model_name_in; 
Rec_car_details car_count_cur%ROWTYPE; 
BEGIN 
OPEN car_count_cur; 
LOOP 
FETCH car_count_cur INTO Rec_car_details; 
EXIT WHEN car_count_cur%NOTFOUND; 
counter := counter + 1; 
END LOOP; 
CLOSE car_count_cur; 
RETURN counter; 
END; 
+1

您沒有按照錯誤消息中指示的那樣傳遞正確數量的參數。看看這個函數,並計算出爲了工作而需要給它的數據,然後做到這一點。 – Ben

+0

嗨,本。我已經包含了我的功能。我是PL/SQL新手,所以我不確定你傳遞參數的含義是什麼? – Splunk

+0

您顯然沒有運行您發佈的相同代碼。第19行是對「findtotalcarmodels」的調用。在你的錯誤信息中,你顯然沒有通過它要求的模型名稱,但是在你的代碼中,你傳遞了'model_name'。另外,我看不到'model_name'來自哪裏。 –

回答

0

好了,所以我不知道爲什麼你得到錯誤使用該功能。該錯誤表明你沒有給函數正確的參數個數。通過功能判斷顯然不是發生了什麼,或者它不是同一個功能。


你剛剛改變了函數調用;該函數需要一個參數,所以你在第一次修改中的「不正確」代碼實際上是正確的。


但是,讓我們把它放在一邊,再看看你在做什麼。

  1. 你的函數是一個表的計數。不需要遊標或循環,遞增變量或任何東西。你可以把它簡化爲

    select count(*) from i_car where model_name = :model_name 
    
  2. 你從來沒有給變量賦值v_countv_maxcount一個值,從而增加他們仍然會導致空。無論如何它們都是日期,所以增加它們有點奇怪。

  3. 你的光標c_date只是另一個計數;再一次不需要循環。

  4. model_name變量永遠不會被初始化,所以你的函數不會返回結果。

有很多方法可以簡化這個;儘管我會在這裏猜測一些事情。更改carcur光標移動到以下幾點:

select i.* 
    , case cost 
      when <= 50000 then 'Budget Car' 
      when <= 100000 then 'Standard Car' 
      else 'Premium Car' 
     end as category 
    , count(*) over (partition by model_name) as total_cars 
from i_cars 

這似乎讓你刪除你的if語句和你的函數。然後,您可以通過執行外刪除你的第二個循環聯接上i_booking(您需要添加主鍵在自己):

select i.* 
    , case c.cost 
      when <= 50000 then 'Budget Car' 
      when <= 100000 then 'Standard Car' 
      else 'Premium Car' 
     end as category 
    , count(distinct c.primary_key) 
     over (partition by c.model_name) as total_cars 
    , count(b.date_reserved) 
     over (partition by b.registration) as reserved_ct 
from i_cars c 
left outer join i_booking b 
    on c.registration = b.registration 

我不是最大的東西100%肯定,因爲它目前尚不清楚在所有它分配的(這不是),但它看起來好像你可能想找到模型等最大計數,在這種情況下,你可以在上面光標使用子查詢:

select sub.* 
    , max(total_cars) over() as max_cars 
    , max(reserved_ct) over() as max_reserved 
    from (select i.* 
       , case c.cost 
        when <= 50000 then 'Budget Car' 
        when <= 100000 then 'Standard Car' 
        else 'Premium Car' 
       end as category 
      , count(distinct c.primary_key) 
       over (partition by c.model_name) as total_cars 
      , count(b.date_reserved) 
       over (partition by b.registration) as reserved_ct 
      from i_cars c 
      left outer join i_booking b 
      on c.registration = b.registration 
       ) sub 

如果再需要來輸出它(很少有需要),你可以遍歷這個單一的SQL語句,它給你所有的東西在o ne go:

declare 

    c_cursor is 
    select sub.* 
     , max(total_cars) over() as max_cars 
     , max(reserved_ct) over() as max_reserved 
     from (select i.* 
        , case c.cost 
         when <= 50000 then 'Budget Car' 
         when <= 100000 then 'Standard Car' 
         else 'Premium Car' 
        end as category 
       , count(distinct c.primary_key) 
        over (partition by c.model_name) as total_cars 
       , count(b.date_reserved) 
        over (partition by b.registration) as reserved_ct 
       from i_cars c 
       left outer join i_booking b 
       on c.registration = b.registration 
        ) sub 

      ; 

begin 

    for i in c_cursor loop 
     dbms_output.put_line(i.registration); 
     dbms_output.put_line(i.cost); 
     ... 
    end loop; 

end; 

我已經將PL/SQL塊和函數減少到單個SQL語句;它可能不是現貨,因爲有那麼多的未知數,但值得爲自己嘗試。簡單幾乎總是更好。

+0

感謝奔,我很欣賞這個答覆,但是我需要保留函數等等。我只需要知道如何從給定的PL/SQL塊中調用它。 – Splunk

+0

你最初發布的是如何調用函數@Splunk;您需要傳入模型名稱,這意味着您需要以某種方式對其進行初始化......但是其餘的代碼都不會按照您期望的方式工作(如果有的話),並且實際上不需要函數在所有... – Ben

+0

是的,我明白你的意思。目前,If語句不起作用,遊標c_date也不會在不使用MAX函數的情況下保留最大日期。其餘的確定。 – Splunk