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;
4

1 回答 1

0

好的,所以我不知道您为什么会在该功能上遇到该错误。该错误表明您没有为函数提供正确数量的参数。从功能来看,这显然不是正在发生的事情,或者它不是同一个功能。


您刚刚更改了函数调用;该函数需要一个参数,因此您在第一个修订版中的“不正确”代码实际上是正确的。


然而,让我们把它放在一边,然后再看看你在做什么。

  1. 您的功能是对表格的计数。不需要游标或循环、递增变量或任何东西。您可以将其简化为

    select count(*) from i_car where model_name = :model_name
    
  2. 您永远不会分配变量v_countv_maxcount值,因此递增它们仍会导致 NULL。无论如何,它们是约会,所以增加它们有点奇怪。

  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% 确定最大的东西,因为它根本不清楚它被分配在哪里(它不是),但看起来你可能想要通过模型等找到最大计数,在这种情况下你可以使用 sub -查询上述光标:

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 语句,它可以一次性为您提供所有内容:

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 语句;它可能不是很准确,因为有很多未知数,但值得自己尝试。简单几乎总是更好。

于 2013-10-17T20:44:41.817 回答