簡體   English   中英

調用“||”時的參數數量或類型錯誤

[英]Wrong number or types of arguments in call to '||'

我們應該讀取一個文本文件,在處理異常的同時將該數據插入到表中。 這是我的函數的代碼:

set serveroutput ON; 
CREATE OR replace FUNCTION Order_func(ldir  VARCHAR2, 
                                      lfile VARCHAR2) 
RETURN BOOLEAN 
AS 
  result       BOOLEAN; 
  f            utl_file.file_type; 
  s            VARCHAR2(200); 
  v_row        VARCHAR2(2000); 
  v1           NUMBER; 
  v2           NUMBER; 
  v3           NUMBER; 
  v4           DATE; 
  v5           DATE; 
  v6           NUMBER; 
  v7           NUMBER; 
  v8           NUMBER; 
  v9           NUMBER; 
  customer_error EXCEPTION; 
  employee_error EXCEPTION; 
  item_error EXCEPTION; 
  customerids  NUMBER; 
  employeeids  NUMBER; 
  inventoryids NUMBER; 
BEGIN 
    SELECT cno 
    INTO   customerids 
    FROM   customers; 

    SELECT employeeno 
    INTO   employeeids 
    FROM   employees; 

    SELECT itemno 
    INTO   inventoryids 
    FROM   inventory; 

    f := utl_file.Fopen(ldir, lfile, 'R'); 

    LOOP 
        utl_file.Get_line(f, v_row); 
        v1 := Substr(v_row, 1, 4); 
        v2 := Substr(v_row, 6, 9); 
        v3 := Substr(v_row, 11, 12); 
        v4 := Substr(v_row, 15, 23); 
        v5 := Substr(v_row, 27, 35); 
        v6 := Substr(v_row, 38, 41); 
        v7 := Substr(v_row, 43); 
        v8 := Substr(v_row, 45, 48); 
        v9 := Substr(v_row, 50, 51); 
        IF v2 <> customerids THEN --checking customer id 
          RAISE customer_error; 
        ELSIF v3 <> employeeids THEN --checking employee id 
          RAISE employee_error; 
        ELSIF v6 <> inventoryids THEN --checking item1 id 
          RAISE item_error; 
        ELSIF v8 <> inventoryids THEN --checking item2 id 
          RAISE item_error; 
        ELSE 
          INSERT INTO transactions 
                      (tid, orderno,  cno,  employeeno,  received, 
                       shipped,  itemno1,  quantity1,  itemno2,  quantity2) 
          VALUES      (sequence_tid.NEXTVAL,  v1,  v2,  v3,  v4,  v5, 
                       v6,  v7,  v8,  v9); 
        END IF; 
    END LOOP; 

    result := TRUE; 

    RETURN result; 
EXCEPTION 
  WHEN customer_error THEN 
dbms_output.Put_line('Customer not found in parent Customer table'); WHEN 
employee_error THEN 
dbms_output.Put_line('Employee not found in Employee table'); 
                     WHEN item_error THEN 
dbms_output.Put_line('Item not found in inventory table'); WHEN OTHERS THEN 
dbms_output.Put_line('Error code:' 
                     || SQLCODE 
                     || '. Error Message: ' 
                     || SQLERRM); 

utl_file.Fclose(f); 

result := FALSE; 

RETURN result; 
END order_func; 

這就是我調用函數的方式(但我認為這是錯誤的):

DECLARE
    results boolean;
BEGIN
    results := order_func('forQues','items.txt');
    DBMS_OUTPUT.PUT_LINE('Result for ORDER_FUNC Function is: ' || results);
END;

這是我遇到的錯誤:

DECLARE
    results boolean;
BEGIN
    results := order_func('forQues','items.txt');
    DBMS_OUTPUT.PUT_LINE('Result for ORDER_FUNC Function is: ' || results);
END;
Error report -
ORA-06550: line 5, column 26:
PLS-00306: wrong number or types of arguments in call to '||'
ORA-06550: line 5, column 5:
PL/SQL: Statement ignored
06550. 00000 -  "line %s, column %s:\n%s"
*Cause:    Usually a PL/SQL compilation error.
*Action:

我試圖刪除 dbms_output 中的結果,這就是發生的事情:

DECLARE
    results boolean;
BEGIN
    results := order_func('forQues','items.txt');
    DBMS_OUTPUT.PUT_LINE('Result for ORDER_FUNC Function is:');
END;

運行后我得到:

Error code:-1422. Error Message: ORA-01422: exact fetch returns more than requested number of rows
Result for ORDER_FUNC Function is:


PL/SQL procedure successfully completed.

請有人幫忙,如何解決這個問題?

除了已經指出的錯誤之外,您的函數至少還有一些問題。 我相信,最大的問題是您對Substring函數的誤解,尤其是第三個參數。 第三個參數可選地指示所需的長度而不是結束位置。 例如,變量 v5 被定義為日期,但值設置為“v5 := Substr(v_row, 27, 35);”。 你真的有一個 35 個字符長的日期嗎? 此外,當省略第三個參數時,結果值將從第二個參數擴展到字符串的末尾。 所以 v7 從位置 43 延伸到字符串的末尾。 V8、V9 分別是 48 位和 51 位的數字,每個字段都與后面的字段重疊。

另一個大問題是錯誤 NO_DATA_FOUND。 您有三個可能發生這種情況的地方(選擇)和 1 個可能發生的地方(utl_file.Get_line - 這就是 utl_file 表示文件結束的方式)。 按照結構,您無法知道是哪個引發了該錯誤。 下面我提出一種方法來解決這個問題。 我將這些元素中的每一個都分解為一個自己的程序。 我將子字符串問題留給您解決。

在此之前有點哲學。 名稱和分類很重要。 名稱應該描述代表什么,但 V1、V2 ... 沒有; 所以可能不是 v5,而是 v_shipped_dt。 同樣,應根據例程的目的來聲明過程與函數。 程序完成事情,功能得到事情。 似乎這里的目的是加載數據而不是返回布爾值。 所以我把它變成了一個過程(它通過一個 out 參數報告)。 (通常我什至不會這樣做。它運行成功並且不返回任何內容,或者如果失敗則引發異常。但這可能是風格。)

create or replace procedure load_order_file 
                          ( ldir  varchar2 
                          , lfile varchar2
                          , result out varchar2
                          ) 
as 
  customer_error exception; 
  employee_error exception; 
  item_error     exception; 

  f            utl_file.file_type; 
  v_row        varchar2(2000); 
  v1           number; 
  v2           number; 
  v3           number; 
  v4           date; 
  v5           date; 
  v6           number; 
  v7           number; 
  v8           number; 
  v9           number; 

  EOF_Reached Boolean ;   

  -- procedure to handle all file processing
  procedure load_order_buffer 
  is
  begin 
     if f is null or not util_file.is_open(f)
     then 
       f := utl_file.fopen(ldir, lfile, 'R'); 
       EOF_Reached := False;
     end if ; 

     utl_file.get_line(f, v_row);
  exception 
    when no_data_found then
      EOF_Reached := True;
      util_file.fclose(f);
  end load_order_buffer;  

  -- procedure to split file line into local variables
  procedure parse_buffer
  is 
  begin
    v1 := substr(v_row, 1, 4);   
    v2 := substr(v_row, 6, 9);   
    v3 := substr(v_row, 11, 12); 
    v4 := substr(v_row, 15, 23); 
    v5 := substr(v_row, 27, 35); 
    v6 := substr(v_row, 38, 41); 
    v7 := substr(v_row, 43);     
    v8 := substr(v_row, 45, 48); 
    v9 := substr(v_row, 50, 51); 
  end parse_buffer; 

  -- procedures to validate customer, employee, and inventory  
  procedure validate_customer(cust_no_in number)
  is 
     l_exists varchar2(1);
  begin 
     select null
       into l_exists 
       from customers
      where cno = cust_no_in; 
  exception 
    when no_data_found then
      raise customer_error;
  end validate_customer;

procedure validate_employee(employee_no_in number)
  is 
    l_exists varchar2(1);
  begin 
     select null
       into l_exists
       from employees
      where employeeno = employee_no_in; 
  exception 
    when no_data_found then
      raise employee_error;
  end validate_employee;  

procedure validate_inventory(inventory_no_in number)
  is 
    l_exists varchar2(1);
  begin 
     select null  
       into l_exists
       from inventory
      where itemno  = inventory_no_in; 
  exception 
    when no_data_found then
      raise item_error;
  end validate_inventory;  
-- Main 
begin 
    -- set up initial assumptions; 
    result := 'Failed'; 
    EOF_Reached := False; 

    loop 
      load_order_buffer;
      exit when EOF_Reached;

      parse_buffer; 
      validate_customer(v2);
      validate_employee(v3);
      validate_inventory(v6);
      validate_inventory(v8);

      -- everything valid create transaction  
      insert into transactions 
               (tid, orderno,  cno,  employeeno,  received, 
                shipped,  itemno1,  quantity1,  itemno2,  quantity2) 
        values (sequence_tid.nextval,  v1,  v2,  v3,  v4,  v5, 
                v6,  v7,  v8,  v9);  
    end loop; 
    result := 'Success';
exception 
  when customer_error then 
       dbms_output.put_line('Customer not found in parent Customer table');
  when employee_error then 
       dbms_output.put_line('Employee not found in Employee table'); 
  when item_error then 
       dbms_output.put_line('Item not found in inventory table');
  when others then 
       dbms_output.put_line('Error code:' 
                          || sqlcode 
                          || '. Error Message: ' 
                          || sqlerrm); 

end load_order_file ;
/

這是一個測試驅動程序

declare 
  result varchar2(8); 
begin
    load_order_file('forQues','items.txt');
    dbms_output.put_line('Load Order file terminated with ' || result);
    if result <> 'Success'
    then 
       rollback; 
    end if ; 
end ; 

由於您既未提供表 DDL 也未提供示例數據,因此未進行測試 祝你好運。

錯誤ORA-01422: exact fetch returns more than requested number of rows當您的查詢返回多行但您有一個只期望返回 1 行的INTO子句時,會發生ORA-01422: exact fetch returns more than requested number of rows

例如,您的三個查詢:

select cno into customerids from customers;
select employeeno into employeeids from employees;
select itemno into inventoryids from inventory;

錯誤PLS-00306: wrong number or types of arguments in call to '||' 被拋出是因為您試圖將一個字符串與一個布爾值連接起來

DBMS_OUTPUT.PUT_LINE('Result for ORDER_FUNC Function is: ' || results); 這是不允許的。

ORA-01422錯誤的可能修復:將您的SELECT放入FOR循環中,例如:

FOR c IN (
    SELECT
        cno
    INTO customerids
    FROM
        customers
) LOOP
    --do stuff, access column value like c.cno
END LOOP;

PLS-00306錯誤的可能修復:將串聯更改為

DBMS_OUTPUT.PUT_LINE('Result for ORDER_FUNC Function is: ' || case when results then 'true' else 'false' end);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM