选择用于Oracle包中的更新

选择用于Oracle包中的更新,oracle,plsql,Oracle,Plsql,我为update语句创建了包和包体 我在书堆里找不到这方面的任何东西, 我不知道我这样做是不是很好, 以及你是否会改变什么 如果我调用程序 begin account_api.upd_account(1, 'user', 1000) end; 在我使用commit语句完成事务之前,应该锁定这些过程 CREATE OR REPLACE PACKAGE account_api AS PROCEDURE upd_account ( p_acc_id

我为update语句创建了包和包体

我在书堆里找不到这方面的任何东西, 我不知道我这样做是不是很好, 以及你是否会改变什么

如果我调用程序

begin
account_api.upd_account(1, 'user', 1000)
end;
在我使用commit语句完成事务之前,应该锁定这些过程

CREATE OR REPLACE PACKAGE account_api AS
PROCEDURE upd_account
          (
            p_acc_id     accounts.acc_id%type
          , p_acc_name   accounts.acc_name%type
          , p_acc_amount accounts.acc_amount%type
      );
end account_api;
 /

CREATE OR REPLACE PACKAGE BODY account_api AS
PROCEDURE upd_account (
            p_acc_id     accounts.acc_id%type
          , p_acc_name   accounts.acc_name%type
          , p_acc_amount accounts.acc_amount%type
)
is
l_current_balance NUMBER;
l_new_balance NUMBER;

BEGIN

  SELECT acc_amount INTO l_current_balance
  FROM accounts
  WHERE acc_id = p_acc_id
  FOR UPDATE;

  l_new_balance := l_current_balance + p_acc_amount;

  IF l_new_balance < 0 THEN
      raise_application_error(-20001, 'Sorry you re overdrawn');
  END IF;

  UPDATE accounts
  SET acc_amount = l_new_balance,
      acc_name = p_acc_name
  WHERE acc_id = p_acc_id;
COMMIT;
end;
end account_api;
/
创建或替换包帐户\u api作为
程序upd_账户
(
会计科目id科目。会计科目id%类型
,p_acc_name帐户。acc_name%类型
,p_acc_金额科目。acc_金额%类型
);
最终账户(api),;
/
创建或替换包体帐户\u api作为
程序upd_账户(
会计科目id科目。会计科目id%类型
,p_acc_name帐户。acc_name%类型
,p_acc_金额科目。acc_金额%类型
)
是
l_当前_余额编号;
l_新_余额编号;
开始
选择账户金额进入当前余额
来自帐户
其中acc_id=p_acc_id
更新;
l_新余额:=l_当前余额+应付账款金额;
如果l_新的_余额<0,则
引发应用程序错误(-20001,“对不起,您透支了”);
如果结束;
更新帐户
设置acc\U金额=l\U新余额,
acc_名称=p_acc_名称
其中acc_id=p_acc_id;
犯罪
终止
最终账户(api),;
/

对我来说,这个过程似乎还可以,但我会将其简化为一条语句,并添加一条显式回滚语句,如下所示:

  UPDATE accounts
  SET acc_amount = acc_amount + p_acc_amount,
      acc_name = p_acc_name
  WHERE acc_id = p_acc_id
  RETURNING acc_amount INTO l_new_balance;
  IF l_new_balance < 0 THEN
      rollback;
      raise_application_error(-20001, 'Sorry you re overdrawn');
  ELSE
      commit;
  END IF;
更新帐户
设置会计科目金额=会计科目金额+会计科目金额,
acc_名称=p_acc_名称
其中acc_id=p_acc_id
将acc_金额返回到l_新余额中;
如果l_新的_余额<0,则
回降;
引发应用程序错误(-20001,“对不起,您透支了”);
其他的
犯罪
如果结束;

无需使用其他
选择。。。FOR UPDATE
以锁定行,因为UPDATE语句也会锁定行。多亏了返回到子句,您可以检索新余额,然后在更新后检查它,如果新余额太低,则回滚更改,否则提交更改。

标题中说要更新,但SELECT语句中没有。为什么?我为更新添加的代码中没有提交sorrylocking在什么之后开始<代码>开始帐户\u api。upd\u帐户(1,'用户',1000)结束UPDATE语句在更改数据之前放置锁。在
begin account\u api.upd\u account(1,'user',1000)结束后,如果发出提交或回滚,锁将保持活动状态我可以立即生成第二条语句,没有任何问题,是否应该出错?我想在其他用户尝试执行updateWell时出错,update语句会持续几毫秒,因此看起来可能会立即运行第二个事务,但实际上,这两个事务都是通过锁序列化的——第一次更新锁定记录,进行更改,然后提交——整个过程持续10-20毫秒。同时,第二个事务将等待记录解锁20毫秒,然后进行第二次更新。