调用“||”时参数的数量或类型错误
Wrong number or types of arguments in call to '||'
我们应该读取一个文本文件,将该数据插入到 table 中,同时处理异常。
这是我的函数的代码:
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.
请有人帮忙,如何解决这个问题?
错误 ORA-01422: exact fetch returns more than requested number of rows
当您的查询 returns 多行但您有一个 INTO
子句只期望返回 1 行时发生。
比如你的三个查询:
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);
除了已经指出的错误之外,您的功能至少还有几个问题。我认为最大的问题是您对 Substring 函数的误解,尤其是第三个参数。第三个参数可选地指示所需的 length 而不是结束位置。例如,变量 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 ... 不代表;所以也许 v_shipped_dt 而不是 v5。同样,应根据例程的目的来声明过程与函数。过程完成事情,功能得到事情。看来这里的目的是加载数据而不是 return 布尔值。所以我把它变成了一个过程(它通过一个输出参数报告)。 (通常我什至不会那样做。它运行成功并且 return 什么都没有,或者如果失败则引发异常。但这可能是风格上的。)
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 ;
由于您既未提供 table DDL 也未提供样本数据,因此 未测试 。祝你好运。
我们应该读取一个文本文件,将该数据插入到 table 中,同时处理异常。 这是我的函数的代码:
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.
请有人帮忙,如何解决这个问题?
错误 ORA-01422: exact fetch returns more than requested number of rows
当您的查询 returns 多行但您有一个 INTO
子句只期望返回 1 行时发生。
比如你的三个查询:
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);
除了已经指出的错误之外,您的功能至少还有几个问题。我认为最大的问题是您对 Substring 函数的误解,尤其是第三个参数。第三个参数可选地指示所需的 length 而不是结束位置。例如,变量 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 ... 不代表;所以也许 v_shipped_dt 而不是 v5。同样,应根据例程的目的来声明过程与函数。过程完成事情,功能得到事情。看来这里的目的是加载数据而不是 return 布尔值。所以我把它变成了一个过程(它通过一个输出参数报告)。 (通常我什至不会那样做。它运行成功并且 return 什么都没有,或者如果失败则引发异常。但这可能是风格上的。)
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 ;
由于您既未提供 table DDL 也未提供样本数据,因此 未测试 。祝你好运。