简体   繁体   English

调用“||”时的参数数量或类型错误

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

We are supposed to read a text file, insert that data into a table while taking care of exceptions.我们应该读取一个文本文件,在处理异常的同时将该数据插入到表中。 This the code for my function:这是我的函数的代码:

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; 

This is how i've called the function (but i think it's wrong):这就是我调用函数的方式(但我认为这是错误的):

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

And this is the error I've got:这是我遇到的错误:

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:

I tried to remove the results in the dbms_output and this is what happened:我试图删除 dbms_output 中的结果,这就是发生的事情:

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

After running this i got:运行后我得到:

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.

Please somebody help, how to fix this?请有人帮忙,如何解决这个问题?

In addition to the errors already pointed out you function has a couple issues, at least.除了已经指出的错误之外,您的函数至少还有一些问题。 The biggest problem is, I believe, your misunderstanding of the Substring function, in particular the 3rd parameter.我相信,最大的问题是您对Substring函数的误解,尤其是第三个参数。 The 3rd parameter optionally indicated the length desired not the ending position.第三个参数可选地指示所需的长度而不是结束位置。 For example the variable v5 is defined as a date but the value is set as "v5 := Substr(v_row, 27, 35);".例如,变量 v5 被定义为日期,但值设置为“v5 := Substr(v_row, 27, 35);”。 Do you really have a date that is 35 characters long.你真的有一个 35 个字符长的日期吗? Additionally when the 3rd parameter is omitted then the resulting value extends from the 2nd parameter to the end of the string.此外,当省略第三个参数时,结果值将从第二个参数扩展到字符串的末尾。 So v7 extends from position 43 to the end of string.所以 v7 从位置 43 延伸到字符串的末尾。 V8, V9 then are numbers that are 48 and 51 digits respectively and every field overlaps the one following. V8、V9 分别是 48 位和 51 位的数字,每个字段都与后面的字段重叠。

The other big issue is the error NO_DATA_FOUND.另一个大问题是错误 NO_DATA_FOUND。 You have three places where this is likely to occur (the selects) and 1 where it will occur (utl_file.Get_line - that's how utl_file indicates end-of-file).您有三个可能发生这种情况的地方(选择)和 1 个可能发生的地方(utl_file.Get_line - 这就是 utl_file 表示文件结束的方式)。 As structured you have no way of knowing which initiated that error.按照结构,您无法知道是哪个引发了该错误。 In the following I propose a method to resolve this issue.下面我提出一种方法来解决这个问题。 I break each of those element into a theit own procedure.我将这些元素中的每一个都分解为一个自己的程序。 I leave the substring issue for you to resolve.我将子字符串问题留给您解决。

Before that a little philosophy.在此之前有点哲学。 Names and classifications are important.名称和分类很重要。 Names should describe what the represent but V1, V2 ... do not;名称应该描述代表什么,但 V1、V2 ... 没有; so instead of v5 perhaps v_shipped_dt.所以可能不是 v5,而是 v_shipped_dt。 Likewise declaring a procedure vs. function should done based on purpose of the routine.同样,应根据例程的目的来声明过程与函数。 Procedures accomplish things, fuunctions get things.程序完成事情,功能得到事情。 It seems the purpose here is to load data not return boolean.似乎这里的目的是加载数据而不是返回布尔值。 So I made it a procedure (it reports back via an out parameter).所以我把它变成了一个过程(它通过一个 out 参数报告)。 (Normally I wouldn't even do that. It runs successfully and returns nothing or if fails raising an exception. But that's perhaps stylistic.) (通常我什至不会这样做。它运行成功并且不返回任何内容,或者如果失败则引发异常。但这可能是风格。)

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

Here is a test driver这是一个测试驱动程序

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 ; 

Since you provided neither table DDL nor sample data this is not tested .由于您既未提供表 DDL 也未提供示例数据,因此未进行测试 Good Luck.祝你好运。

Error ORA-01422: exact fetch returns more than requested number of rows happens when your query returns multiple rows but you have an INTO clause which only expects 1 row to be returned.错误ORA-01422: exact fetch returns more than requested number of rows当您的查询返回多行但您有一个只期望返回 1 行的INTO子句时,会发生ORA-01422: exact fetch returns more than requested number of rows

For example, your three queries:例如,您的三个查询:

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

Error PLS-00306: wrong number or types of arguments in call to '||'错误PLS-00306: wrong number or types of arguments in call to '||' is thrown because you are trying to concatenate a string with a boolean at被抛出是因为您试图将一个字符串与一个布尔值连接起来

DBMS_OUTPUT.PUT_LINE('Result for ORDER_FUNC Function is: ' || results); which is not allowed.这是不允许的。

Possible fixes for ORA-01422 error: Put your SELECT in a FOR loop like: ORA-01422错误的可能修复:将您的SELECT放入FOR循环中,例如:

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

Possible fixes for PLS-00306 error: Change the concatenation to 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