显式游标pl / sql

时间:2016-11-25 18:17:24

标签: sql plsql

构建一个PL?SQL匿名块,用于更改客户的信用额度。使用和显式游标以及您选择的循环来完成任务。此外,记录更新了多少条记录并显示以下消息:“XX客户记录已更新”。确保在循环完成后提交所有hte记录。以下是当前信用额度和新信用额度的图表。

(旧)10,000(新)25,000,

(旧)5,000(新)10,000,

(旧)7,000(新)15,000,

(旧)3,000(新)5,000,(此表中的内容多于这4个)。

这是我的代码,显然不起作用。预先感谢您的帮助。非常感谢。

    set serveroutput on
Declare
 Cursor c_credit_cursor is
  Select custid, creditlimit
  From customer
  where creditlimit = 10000
  or creditlimit = 5000 
  or creditlimit = 7000 
  or creditlimit = 3000
  and customer.custid = v_custid;
  v_creditlimit customer.creditlimit%TYPE;
  v_custid customer.custid%TYPE;
Begin
LOOP
open c_credit_cursor;
  Loop Fetch c_credit_cursor INTO v_custid, v_creditlimit;
  If v_creditlimit = 10000 then
    update c_credit_cursor
    set v_creditlimit = 25000;
  elsif v_creditlimit = 5000 then
    update c_credit_cursor
    set v_creditlimit = 10000;
  elsif v_creditlimit = 7000 then
    update c_credit_cursor
    set v_creditlimit = 15000;
  elsif v_creditlimit = 3000 then
    update c_credit_cursor
    set v_creditlimit = 5000;
  End If;
  DBMS_OUTPUT.PUT_LINE (v_custid ||' customer records were updated.');
  End Loop;
    commit;
    Exit When c_credit_cursor%NOTFOUND;
    Close c_credit_cursor;
  END Loop;
  End;

1 个答案:

答案 0 :(得分:1)

您的代码存在许多问题:

首先,光标的条件为customer.custid = v_custid。无论客户ID是什么,您都想要遍历所有客户:您只对那些具有指定信用额度的客户感兴趣。 (事实上​​,稍后在您的代码中,您正在将游标中的客户ID读入v_custid,因此尝试将v_custid放回光标是没有意义的。我建议从光标中删除此条件。

接下来,您需要两个END LOOP语句的原因是您有两个LOOP语句。每个LOOP必须以END LOOP终止。我不知道为什么你有外循环 - 你应该只需要一个 - 所以删除第一个LOOP(仅在Begin之后)和第二个END LOOP

下一个问题是update语句。每个update c_credit_cursor语句都会出错table or view does not exist。原因是您无法像这样更新游标,只能更新表格。该错误告诉您它无法找到名为c_credit_cursor的表。您还需要在表格中指定要更新的列名称:您不能使用v_creditlimit作为本地变量。您想要使用creditlimit

有两种方法可以修复update语句。您可以使用从光标读出的客户ID更新客户:

update customer
   set credit_limit = (new credit limit)
 where custid = v_custid;

或者,您可以更新光标的当前行:

update customer
   set credit_limit = (new credit limit)
 where current of c_credit_cursor;

第二种方法要求您在FOR UPDATE声明的末尾添加CURSOR

接下来,您将收到有关在循环外使用EXIT的错误消息。你有一个Exit When声明,但说实话,它在错误的地方。你真的希望你的Exit When语句成为Fetch语句之后的第一件事:如果我们试图从光标中读取数据但没有得到更多数据,那么我们没有理由继续留在循环中,所以我们需要摆脱它。

最后,我要指出打印出更新的客户记录数量的行不会总是打印出正确的输出。它没有打印出更新的记录数,它只打印出更新的最后一条记录的客户ID。如果您的数据库中有五个客户记录,ID为1到5,则所有五个都有您的循环更新的信用额度,并且数据库最后会返回ID为5的记录,那么您的代码将输出5 customer records were updated 。在这种情况下,您的代码将打印正确的答案,但这只是巧合。如果客户的ID为1001到1005,会发生什么?

<击> 您需要添加另一个局部变量来计算光标读取的记录数,然后使用它。