以下是使用2个参数的过程:customer_code和pay_amount。 该过程按预期工作,但是当我输入错误的cus_code时,我得到错误而不是我的自定义检查:
ORA-01403: no data found
ORA-06512: at "XXXXX.CUST_PAY", line 19
ORA-06512: at line 2
程序:
CREATE OR REPLACE PROCEDURE cust_pay (temp_ccode IN NUMBER, pay_amount IN NUMBER)AS
BEGIN
DECLARE
Value_check NUMBER;
cbalance NUMBER;
BEGIN
SELECT Count(cus_code)
INTO value_check
FROM customer
WHERE cus_code = temp_ccode;
IF value_check IS NULL THEN
Dbms_Output.put_line('the value was not FOUND');
ELSE
UPDATE customer
SET cus_balance = cus_balance - pay_amount
WHERE cus_code = temp_ccode;
SELECT cus_balance
INTO cbalance
FROM customer
WHERE cus_code = temp_ccode;
IF cbalance < 0 THEN
Dbms_Output.put_line('The client owes us ' || cbalance);
ELSE
Dbms_Output.put_line('Customer new balance is ' || cbalance);
END IF;
END IF;
END;
END;
我做错了什么?我是客人,我需要在发出SELECT请求之前检查该值,对吗?
答案 0 :(得分:2)
您的问题实际上是由您的支票引起的:
SELECT COUNT (cus_code)
INTO value_check
FROM customer
WHERE cus_code = temp_ccode;
以上查询将从不返回NULL,这是您要检查的内容。如果表中的值与参数temp_ccode
不匹配,则value_check
将为0.这反过来意味着您的IF语句不正确,这会导致您的代码稍后出现错误。
虽然有一种更简单,更有效的方法。您可以使用SQL%ROWCOUNT查看更新对受影响的行数。如果返回值为0,则表示您的客户不存在。
create or replace procedure cust_pay (
Ptemp_ccode in number
, Ppay_amount in number
) is
l_balance number;
begin
update customer
set cus_balance = cus_balance - Ppay_amount
where cus_code = Ptemp_ccode;
if SQL%ROWCOUNT = 0 then
dbms_output.put_line('The customer was not found.');
else
select cus_balance
into l_balance
from customer
where cus_code = temp_ccode;
if l_balance < 0 then
dbms_output.put_line('the client owes us ' || l_balance);
else
dbms_output.put_line('customer new balance is ' || l_balance);
end if;
end if;
end;
这里不需要处理select... into ...
中的NO_DATA_FOUND异常,因为您已经保证UPDATE语句存在cus_code
。
请注意我所做的其他更改:
一般来说,你不应该在PL / SQL块中使用dbms_ouput.put_line
,因为你有在那里看看发生了什么。它适用于调试过程,但在生产代码中相当无用。
也可以使用RETURN statement来避免嵌套的IF语句,我认为这使代码更清晰,更容易阅读;虽然这是一个判断电话。
create or replace procedure cust_pay (
Ptemp_ccode in number
, Ppay_amount in number
) is
l_balance number;
begin
update customer
set cus_balance = cus_balance - Ppay_amount
where cus_code = Ptemp_ccode;
if SQL%ROWCOUNT = 0 then
return;
end if;
select cus_balance
into l_balance
from customer
where cus_code = temp_ccode;
if l_balance < 0 then
dbms_output.put_line('The client owes us ' || l_balance);
else
dbms_output.put_line('New balance is ' || l_balance);
end if;
end;
所有这些都假定您的CUSTOMER表在cus_code
上是唯一的。
答案 1 :(得分:2)
您的代码的更正版本在此处:
CREATE OR REPLACE PROCEDURE cust_pay (temp_ccode IN NUMBER, pay_amount IN NUMBER) AS
Value_check NUMBER;
cbalance NUMBER;
BEGIN
SELECT Count(cus_code)
INTO value_check
FROM customer
WHERE cus_code = temp_ccode;
IF value_check = 0 THEN
Dbms_Output.put_line('the value was not FOUND');
ELSE
UPDATE customer
SET cus_balance = cus_balance - pay_amount
WHERE cus_code = temp_ccode
RETURNING cus_balance
INTO cbalance;
IF cbalance < 0 THEN
Dbms_Output.put_line('The client owes us ' || -cbalance);
ELSE
Dbms_Output.put_line('Customer new balance is ' || cbalance);
END IF;
END IF;
END;
答案 2 :(得分:2)
基于我在其他答案中提倡的原则,如果你更新一个不存在的客户的余额并不重要,你可以结合我自己和Egor的答案来提出这个:
create or replace procedure cust_pay (
Ptemp_ccode in number
, Ppay_amount in number
) is
l_balance number;
begin
update customer
set cus_balance = cus_balance - Ppay_amount
where cus_code = Ptemp_ccode
returning cus_balance
into l_balance;
if SQL%ROWCOUNT = 0 then
dbms_output.put_line('The customer was not found.');
elsif l_balance < 0 then
dbms_output.put_line('The client owes us ' || l_balance);
else
dbms_output.put_line('New balance is ' || l_balance);
end if;
end;
在一个声明中做所有事情的好处是速度的提高。再次,您不必担心NO_DATA_FOUND异常,因为您只进行了更新。
我在之前的回答中说的所有内容仍然适用,count(*)
中的select... into...
永远不会返回null,总是一个数字。
答案 3 :(得分:0)
您可以在sql查询之前检查以验证参数值
另一种方法是使用EXCEPTION NO_DATA_FOUND
CREATE OR REPLACE PROCEDURE cust_pay (temp_ccode IN NUMBER,
pay_amount IN NUMBER,errcode OUT NUMBER)
AS
BEGIN
DECLARE
Value_check NUMBER;
cbalance NUMBER;
BEGIN
SELECT COUNT (cus_code)
INTO value_check
FROM customer
WHERE cus_code = temp_ccode;
IF value_check IS NULL
THEN
DBMS_OUTPUT.put_line ('the value was not FOUND');
ELSE
UPDATE customer
SET cus_balance = cus_balance - pay_amount
WHERE cus_code = temp_ccode;
SELECT cus_balance
INTO cbalance
FROM customer
WHERE cus_code = temp_ccode;
IF cbalance < 0
THEN
DBMS_OUTPUT.put_line ('The client owes us ' || cbalance);
ELSE
DBMS_OUTPUT.put_line ('Customer new balance is ' || cbalance);
END IF;
END IF;
END;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
DBMS_OUTPUT.put_line ('no data***' || SQLERRM);
errcode := 1;
END;