`

银行转账

 
阅读更多

 

 

 

CREATE TABLE acct(acct_no NUMBER, balance NUMBER);
CREATE TABLE locking(acct_no NUMBER, type VARCHAR2(8));
CREATE TABLE holding(acct_no NUMBER, amount NUMBER);

INSERT INTO acct VALUES(10001, 2000);
INSERT INTO acct VALUES(10002, 500);
INSERT INTO acct VALUES(10003, 1500);
INSERT INTO acct VALUES(10004, 300);

INSERT INTO locking VALUES(10004, 'locked');

INSERT INTO holding VALUES(10001, 1000);
INSERT INTO holding VALUES(10003, 800);
commit;

  /************************************************
   使用源表名称:holding 冻结账户信息表
                 Locking锁定账户信息表
                 acct账户信息表
   功能描述:账户间转账
             a) 确定转出账户没有被锁。
             b) 确定转入账户的存在。
             c) 确定转入账户没有被锁。
             d) 确定转出账户中有足够余额满足转账 
             e) 确定转出账户在转账后满足冻结额的要求
             f) 确定在转出账户上成功地扣去了转账的金额
             g) 确定在转入账户上成功地加上了转账的金额
   参数说明:transfer_in 资金转入账户
             transfer_out 资金转出账户
             transfer_balance 转账金额
             oi_flag 返回标志 0-正常 -1 失败
             os_msg 返回信息 
  ************************************************/
  create or replace 
  PROCEDURE transfer_account(transfer_in      IN NUMBER,
                             transfer_out     IN NUMBER,
                             transfer_balance IN NUMBER,
                             oi_flag          OUT PLS_INTEGER,
                             os_msg           OUT VARCHAR2) AS
    balance_after_transfer acct.balance%TYPE; --转账后的余额
  BEGIN
    oi_flag := 0;
    os_msg  := 'success';
    IF transfer_in = transfer_out THEN
      oi_flag := -1;
      os_msg  := '转入、转出账户相同,不必转账';
      RETURN;
    END IF;
    --a) 确定转出账户没有被锁。
    IF (is_account_lock(transfer_out) = 0) THEN
      oi_flag := -1;
      os_msg  := '转出账户被锁定';
      RETURN;
    END IF;
    --b)  确定转入账户的存在。
    IF (is_account_exist(transfer_in) = -1) THEN
      oi_flag := -1;
      os_msg  := '转入账户不存在';
      RETURN;
    END IF;
    --c)  确定转入账户没有被锁。
    IF (is_account_lock(transfer_in) = 0) THEN
      oi_flag := -1;
      os_msg  := '转入账户被锁定';
      RETURN;
    END IF;
    --d)  确定转出账户中有足够余额满足转账 
    DECLARE
      num_transfer_balance acct.balance%TYPE;
    BEGIN
      SELECT balance
        INTO num_transfer_balance
        FROM acct
       WHERE acct_no = transfer_out;
      IF num_transfer_balance < transfer_balance THEN
        oi_flag := -1;
        os_msg  := '转出账户余额不足,当前余额为' || num_transfer_balance;
        RETURN;
      END IF;
      balance_after_transfer := num_transfer_balance - transfer_balance;
    EXCEPTION
      WHEN no_data_found THEN
        oi_flag := -1;
        os_msg  := '转出账户不存在';
        RETURN;
      WHEN too_many_rows THEN
        oi_flag := -1;
        os_msg  := '转出账户不唯一';
        RETURN;
        --注意这里不加when others,通用异常放外围
    END;
    --e)  确定转出账户在转账后满足冻结额的要求
    --对冻结账户执行判断
    IF is_account_holding(transfer_out) = 0 THEN
      DECLARE
        num_hoding_balance holding.amount%TYPE;
      BEGIN
        SELECT amount
          INTO num_hoding_balance
          FROM holding
         WHERE acct_no = transfer_out;
        IF num_hoding_balance > balance_after_transfer THEN
          oi_flag := -1;
          os_msg  := '该账户为冻结账户,转账后余额低于冻结额,当前冻结额为' || num_hoding_balance;
          RETURN;
        END IF;
      EXCEPTION
        WHEN no_data_found THEN
          oi_flag := -1;
          os_msg  := '冻结账户不存在' || '输入账号为' || transfer_out;
          RETURN;
        WHEN too_many_rows THEN
          oi_flag := -1;
          os_msg  := '冻结账户不唯一' || '输入账号为' || transfer_out;
          RETURN;
      END;
    END IF;
    --f)  确定在转出账户上成功地扣去了转账的金额
    UPDATE acct
       SET balance = balance - transfer_balance
     WHERE acct_no = transfer_out;
    IF SQL%ROWCOUNT <> 1 THEN
      oi_flag := -1;
      os_msg  := '更新转出账户余额失败';
      RETURN;
    END IF;
    --g)  确定在转入账户上成功地加上了转账的金额
    UPDATE acct
       SET balance = balance + transfer_balance
     WHERE acct_no = transfer_in;
    IF SQL%ROWCOUNT <> 1 THEN
      oi_flag := -1;
      os_msg  := '更新转入账户余额失败';
      RETURN;
    END IF;
    
    COMMIT;
  EXCEPTION
    WHEN OTHERS THEN
      oi_flag := -1;
      os_msg  := '转账出现异常,异常信息为' || SQLERRM || '|' || SQLCODE;
      ROLLBACK;
      --此处日志未处理,有兴趣可自行参考前面的例子补充上
  END;
  
  
  
  
  /************************************************
   使用源表名称:locking锁定账户信息表
   功能描述:账号是否被锁,返回0时被锁
   参数说明:acctno 账号
  ************************************************/
  create or replace 
  FUNCTION is_account_lock(acctno acct.acct_no%TYPE) RETURN PLS_INTEGER AS
    lock_acc_num PLS_INTEGER;
  BEGIN
    SELECT COUNT(1) INTO lock_acc_num FROM locking WHERE acct_no = acctno;
    IF lock_acc_num > 0 THEN
      RETURN 0;
    ELSE
      RETURN - 1;
    END IF;
  END is_account_lock;

  /************************************************
   使用源表名称:acct锁定账户信息表
   功能描述:账号是否存在,返回-1不存在
   参数说明:acctno 账号  
  ************************************************/
  create or replace 
  FUNCTION is_account_exist(acctno acct.acct_no%TYPE) RETURN PLS_INTEGER AS
    acc_num PLS_INTEGER;
  BEGIN
    SELECT COUNT(1) INTO acc_num FROM acct WHERE acct.acct_no = acctno;
    IF acc_num > 0 THEN
      RETURN 0;
    ELSE
      RETURN - 1;
    END IF;
  END is_account_exist;
  /************************************************
   使用源表名称:holding 冻结账户信息表
   功能描述:账号是否冻结
   参数说明:acctno 账号
  ************************************************/
  create or replace 
  FUNCTION is_account_holding(acctno acct.acct_no%TYPE) RETURN PLS_INTEGER AS
    acc_num PLS_INTEGER;
  BEGIN
    SELECT COUNT(1) INTO acc_num FROM holding WHERE acct_no = acctno;
    IF acc_num > 0 THEN
      RETURN 0;
    ELSE
      RETURN - 1;
    END IF;
  END is_account_holding;
/

另附测试程序
CREATE OR REPLACE PACKAGE account_test IS
  --转账程序测试集
  PROCEDURE transfer_account_test(oi_flag OUT PLS_INTEGER,
                                  os_msg  OUT VARCHAR2);
  --测试
  PROCEDURE is_account_lock_test(oi_flag OUT PLS_INTEGER,
                                 os_msg  OUT VARCHAR2);
END account_test;
/
CREATE OR REPLACE PACKAGE BODY account_test IS
  --测试案例集
  PROCEDURE transfer_account_test(oi_flag OUT PLS_INTEGER,
                                  os_msg  OUT VARCHAR2) AS
  BEGIN
    oi_flag := 0;
    os_msg  := 'success';
    --a) 确定转出账户没有被锁。
    is_account_lock_test(oi_flag, os_msg); --测试函数is_account_lock
    IF oi_flag = -1 THEN
      RETURN;
    END IF;
    --传入锁定转出账户
    account.transfer_account(10001, 10004, 1, oi_flag, os_msg);
    IF oi_flag = 0 THEN
      RETURN;
    END IF;
    --传入非锁定转出账户
    account.transfer_account(10001, 10002, 1, oi_flag, os_msg);
    IF oi_flag = -1 THEN
      RETURN;
    END IF;
    --b) 确定转入账户的存在。
    --传入非法的转入账户10009
    account.transfer_account(10009, 10002, 1, oi_flag, os_msg);
    IF oi_flag = 0 THEN
      RETURN;
    END IF;
    --传入合法的转入账户10001
    account.transfer_account(10001, 10002, 1, oi_flag, os_msg);
    IF oi_flag = -1 THEN
      RETURN;
    END IF;
    --c) 确定转入账户没有被锁。
    --传入锁定的转入账户
    account.transfer_account(10004, 10002, 1, oi_flag, os_msg);
    IF oi_flag = 0 THEN
      RETURN;
    END IF;
    --传入非锁定的转入账户
    account.transfer_account(10001, 10002, 1, oi_flag, os_msg);
    IF oi_flag = -1 THEN
      RETURN;
    END IF;
    --d) 确定转出账户中有足够余额满足转账 
    --传入超大的金额
    account.transfer_account(10001, 10002, 100000, oi_flag, os_msg);
    IF oi_flag = 0 THEN
      RETURN;
    END IF;
    --传入正常的金额按(f)、(g)的案例覆盖
    /*account.transfer_account(10001, 10002, 1, oi_flag, os_msg);
    IF oi_flag = -1 THEN
      RETURN;
    END IF;*/
    --e) 确定转出账户在转账后满足冻结额的要求
    --传入冻结账户并且不满足冻结金额要求 10003账户转出1000后将不满足要求
    account.transfer_account(10001, 10003, 1000, oi_flag, os_msg);
    IF oi_flag = 0 THEN
      RETURN;
    END IF;
    --传入冻结账户满足冻结金额要求
    account.transfer_account(10002, 10001, 1, oi_flag, os_msg);
    IF oi_flag = -1 THEN
      RETURN;
    END IF;
    --传入非冻结账户以下案例可覆盖
    --f) 确定在转出账户上成功地扣去了转账的金额
    account.transfer_account(10003, 10002, 1, oi_flag, os_msg);
    IF oi_flag = -1 THEN
      RETURN;
    END IF;
    --g) 确定在转入账户上成功地加上了转账的金额
    account.transfer_account(10003, 10002, 1, oi_flag, os_msg);
    IF oi_flag = -1 THEN
      RETURN;
    END IF;
  END;
  --测试账户是否锁定
  PROCEDURE is_account_lock_test(oi_flag OUT PLS_INTEGER,
                                 os_msg  OUT VARCHAR2) AS
  BEGIN
    /*测试函数is_account_lock
    */
    oi_flag := 0;
    os_msg  := 'success';
    DECLARE
      expect_account locking.acct_no%TYPE := 10004; --已锁定的账户
      expect_result  PLS_INTEGER := 0; --期望为锁定
      real_resutl    PLS_INTEGER;
    BEGIN
      real_resutl := account.is_account_lock(expect_account);
      IF expect_result = real_resutl THEN
        RETURN;
      ELSE
        oi_flag := -1;
        --此处加上拼接,便于在测试集中调用且不会丢失其他测试程序的结果,注意要加上字符数限制
        os_msg := substrb(os_msg || '|bug in is_account_lock,期望值:' ||
                          expect_result || '实际值:' || real_resutl || '|',
                          1,
                          1000);
      END IF;
    END;
  END;
END account_test;
/

 

分享到:
评论

相关推荐

    图形界面银行转账小助手

    《图形界面银行转账小助手详解》 在信息技术日益发达的今天,银行转账已经不再局限于传统的柜台操作,而是逐渐转向了更为便捷的电子化服务。"图形界面银行转账小助手"正是这样一款应用,它利用Java编程语言,构建了...

    模拟银行转账功能android数据库例子

    在Android应用开发中,模拟银行转账功能通常涉及到用户账户余额的增减操作,这就需要一个可靠的存储机制来保存和管理这些数据。SQLite是Android系统内置的关系型数据库,它轻量级、高效且易于使用,因此成为了实现这...

    数据库大作业银行转账系统(前后端完整实现)

    数据库大作业银行转账系统是一个完整的项目,它涵盖了数据库设计、后端开发以及前端展示等多个关键环节。这个系统基于Mysql数据库和Java编程语言,利用三层架构实现后端逻辑,前端则使用HTML进行页面构建。 首先,...

    模拟银行转账

    在本项目中,“模拟银行转账”是一个基于Java的桌面应用程序,使用了Swing框架来构建用户界面。这个系统旨在模拟实际银行的转账操作,而不用真正的数据库,而是通过集合类来模拟数据库的功能。以下是关于这个项目的...

    SSH三大框架模拟银行转账

    在银行转账这样的业务场景中,它们各自承担着关键的角色。 Struts2作为MVC(Model-View-Controller)框架,负责处理用户请求并控制应用程序的流程。它提供了一种组织应用程序结构的方式,使得业务逻辑与视图和控制...

    银行转账程序 ,仅供参考

    总的来说,这个“银行转账程序”涉及到MyBatis的使用、数据库设计、业务逻辑处理、事务管理和安全性等多个方面,是一个综合性的Java应用示例,有助于学习和理解如何在实际项目中运用MyBatis框架。通过分析和改进这样...

    简单的银行转账就是实现事务管理

    在IT行业中,事务管理是确保数据一致性、完整性和可靠性的关键机制,特别是在处理金融交易时,如银行转账。本文将深入探讨"简单的银行转账就是实现事务管理"这一主题,以及与之相关的知识点。 首先,我们需要理解...

    数据库银行转账系统python实现.rar

    某电数据库课程设计大作业 实现一个银行转账系统 需要连接数据库以及设计UI 需要导入第三方库pyqt5 以及 pymysql模块 在进行一个应用系统的开发过程中,从上到下一般需要四个构件:客户端-业务逻辑层-数据访问层-...

    基于android的银行转账系统,是作为《工业App设计与实现》课程的期末作业

    这份资源包括一个基于Android平台的简单银行转账系统,专为大学生设计,以及相应的结课报告。这个银行转账系统允许用户创建账户、进行转账操作和查看交易历史,而结课报告则详细记录了设计和实现这个应用的过程。 ...

    SQL Server事务银行转账

    SQL Server事务银行转账,转账时间,卡号密码等,实现银行转账存储过程事务实现,jiandnayidong

    sql 实现银行转账

    帐户表(帐号,姓名,余额,锁定) 业务需求: 1.两个帐号都要存在。 2.如果任何一方被锁定(锁定字段=1),则不能转。 3.转账方最低余额为10元。 3.要保证交易完整性。

    银行的简单转账代码(java)

    在Java编程语言中,实现一个简单的银行转账功能是学习面向对象设计和基本的银行业务逻辑的一个常见练习。这个代码示例可能包含用户类(User)、账户类(Account)以及转账类(Transfer)等核心组件。下面将详细介绍这些...

    java多线程模拟处理银行的实时转账交易

    在Java编程领域,多线程技术是实现并发执行任务的关键工具,尤其在处理实时系统如银行转账交易时显得尤为重要。银行转账涉及到多个账户之间的资金流动,这种操作通常需要高效、安全且并发地进行。本项目"java多线程...

    银行转账系统-课程设计

    在本次课程设计中,我们将构建银行日常管理系统、证券方的日常管理系统以及银证转账系统。这个项目旨在让学生熟悉实际的金融信息系统开发过程,理解系统分析、设计、实施和测试的各个环节。 开发工具选择对于项目的...

    银行转账代码

    一个简单的银行转账的开源代码,适用于学习。

    jsp+sql2000银行转账系统

    【银行转账系统基于JSP与SQL2000的实现】 在互联网技术高速发展的今天,银行转账系统的在线实现已经成为银行业务的重要组成部分。本系统利用JavaServer Pages(JSP)技术结合SQL Server 2000数据库,构建了一个简单...

    银行转账系统分析与设计.pdf

    银行转账系统分析与设计 银行转账系统是银行业务的核心部分,旨在提供快速、安全、可靠的转账服务。该系统的设计和开发是非常复杂的,涉及到多个方面的技术和业务要求。本文将对银行转账系统进行分析和设计,包括...

    SQL存储过程的应用(ATM银行转账系统)

    本主题将深入探讨如何在ATM(自动取款机)银行转账系统中应用SQL存储过程,以实现高效、安全的数据操作。 一、存储过程的优点 1. 提高性能:存储过程在首次被创建时会被编译成数据库内部的二进制格式,之后每次调用...

    基于C++开发的虚拟的银行转账系统源码+详细图文说明(期末大作业&课程设计&项目开发)

    基于C++开发的虚拟的银行转账系统源码+详细图文说明,适合期末大作业、课程设计、项目开发。项目源码已经过严格测试,可以放心下载使用~ 基于C++开发的虚拟的银行转账系统源码+详细图文说明,适合期末大作业、课程...

    银行转账事务小练习.zip

    银行转账事务的小练习,简单的简单表述了事务的四大特性(原子性:要么全部完成,要么全部不完成;一致性:事务开始之前和事务结束以后,数据库的完整性没有被破坏;持久性:事务完成以后,该事务对数据库的更改持久保存在...

Global site tag (gtag.js) - Google Analytics