热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

数据库技术:存储过程介绍以及使用(转账,分页)

课堂上老师让人报名讲课,在“触发器”、“存储过程”、“连接”中选择一个内容,

课堂上老师让人报名讲课,在“触发器”、“存储过程”、“连接”中选择一个内容,那时还没学过“触发器”和“存储过程”,所以我报名要讲“存储过程”。

然后花了两个星期,有空就查查资料,测试代码,应该也算是理解了大概了吧。

成果有:1.简单的ppt介绍存储过程;2.数据库创建、运行“存储过程”;3.应用程式连接数据库调用存储过程

下面按照我在课堂上讲的ppt流程写下文字教程,希望大家对存储过程有个整体的认识。
我的微薄:http://weibo.com/u/2448939884 欢迎程序员互粉。

一:简介

存储过程介绍以及使用(转账,分页)

存储过程确实像是高级语言中的“方法”、“函数”,里面可以封装很多的sql语句等代码,这些代码联合起来会实现某个功能,即某个需求。若一存储过程完成对某功能的封装后,就像一个盒子,外部想使用它的时候,无需关心内部的代码,只需把调用该盒子,将一些参数传进去(可以没有参数)。存储过程在内部运行,操作数据库数据,然后可以有返回值送回给它的调用者。

 二:优缺点

存储过程介绍以及使用(转账,分页)

存储过程确实有不少优点!

1.运行速度快。

但当时只知道并不是因为它的执行速度快,对“体现在预编译”也没什么理解。还好讲课后有同学问到,然后老师调拨了下:当客户端第一次调用该存储过程时,数据库会进行编译等操作,然后把“过程”存到内存中,这第一次会比较慢。当客户端(可以是不同的客户端)之后再次调用该存储过程时,便是直接从内存中执行,从而速度比较快。

2.可以降低网络通信量

为什么可以可以降低网络通信量?一开始我也是摸不着头脑,和“客户端直接写sql语句”相比,同样都差不多是发送一个请求去数据库,同样数据库可能返回一个结果集,到底在哪个方面上可以降低了网络通信量?

后来找到了一个例子,焕然大悟。这个例子就是“有分页功能”的存储过程。可以想象一下,如果有一张表有100万行数据,如果在客户端写一条sql语句让这100行数据抓回客户端,然后再写个for循环让它们分页显示,这得消耗多大的资源啊!

现在有了存储过程,就可以让客户端把“每页要显示的行数”和“第几页”的参数传到数据库的存储过程,存储过程再去获取对应的页面的数据,然后在把该页数据返回给客户端。这样降低的网络通信量将是大大的!

除此之外,还有一些挺不错的优点

3.提高安全性

因为客户端只是发送一个调用某存储过程的命令到服务器,这时就算该信息被截取了,对方也不知道该存储过程是做了什么事。

4.便于集中控制。

像一些可能要经常改变运算规则的运算放到存储过程中,需要修改时对存储过程进行修改就行。打个比方,一个数据库,多个客户端,如果不使用存储过程,修改操作数据库的sql语句时,就要更新修改所有客户端。

 

缺点不多,但肯定有,不然全部用存储过程来处理数据好了呵呵。但暂时不能很好的体会,就不乱写了……

三:实例需求

存储过程介绍以及使用(转账,分页)

这里有个叫atm的数据库,里面有一张t_users的表,里面存在id、姓名、余额的信息

存储过程介绍以及使用(转账,分页)

简单的转账功能:即a向b转账金额c,a的余额减去c,b的余额加上c

分页:即显示某页面的数据

四:实例流程

存储过程介绍以及使用(转账,分页)

这张图表示了数据库向应用程序返回数据的两个方式。后来老师提到,我应该多画几个“应用程序”,体现下存储过程的便利。如果不使用存储过程,那应用程序有时要完成某个个功能,将不知一次地向数据库发送请求。比如,有可能要去获取一个数据到应用程序进行判断,符合条件了,再发送另一个执行命令到数据库。而采用存储过程,则直接调用存储过程即可,它在里面判断是否符合条件后进行不同操作返回不同的值给应用程序。

五:演示(这里使用的sql server 2008 + vs2010 的c# & wpf & ado.net)

存储过程介绍以及使用(转账,分页)

1.数据库创建一个存储过程:

在数据库atm中,新建查询,执行以下代码

  1. create procedure transferaccounts (@fromid int, @money decimal, @toid int)
  2. as
  3. –如果(余额>转账)的代码省略
  4. –委托的代码省略
  5. begin –begin~end相当于高级语言的 { }
  6. update t_users set balance = balance – @money where id = @fromid
  7. update t_users set balance = balance + @money where id = @toid
  8. return 1 –返回值
  9. end
  10. go
  create procedure transferaccounts (@fromid int, @money decimal, @toid int)   as   --如果(余额>转账)的代码省略   --委托的代码省略   begin  --begin~end相当于高级语言的  {  }    update t_users set balance = balance - @money where id = @fromid    update t_users set balance = balance + @money where id = @toid    return 1 --返回值   end   go

 

2.数据库可视化编辑一个存储过程:

目录位置:数据库–atm–可性–存储过程,会看到transferaccounts 。右键点击它,可以修改、删除等操作

3.数据库可视化执行一个存储过程:

右键点击transferaccounts,编写存储过程脚本为–execute 到 新查询编辑器窗口

  1. declare @rc int
  2. declare @fromid int
  3. declare @money decimal(18,0)
  4. declare @toid int
  5.  
  6. — todo: 在此处设置参数值。
  7. set @fromid = 1
  8. set @toid = 2
  9. set @mOney= 100
  10.  
  11. execute @rc = [atm].[dbo].[transferaccounts]
  12. @fromid
  13. ,@money
  14. ,@toid
  15. go
  declare @rc int  declare @fromid int  declare @money decimal(18,0)  declare @toid int    -- todo: 在此处设置参数值。  set @fromid = 1  set @toid = 2  set @mOney= 100    execute @rc = [atm].[dbo].[transferaccounts]      @fromid    ,@money    ,@toid  go  

 

(浅蓝色部分为手动添加的参数值)

执行之后,结果正确

存储过程介绍以及使用(转账,分页)

4.程序连接数据库执行一个存储过程:

这里就只能简单说下了。

存储过程介绍以及使用(转账,分页)

首先在sqlhelper中编写一个执行的存储过程的方法

  1. public static bool executeprocedure(string procedurename, params sqlparameter[] parameters)
  2. {
  3. using (sqlconnection cOnn= new sqlconnection(connstr))
  4. {
  5. conn.open();
  6. using (sqlcommand cmd = conn.createcommand())
  7. {
  8. cmd.commandtext = procedurename;
  9. cmd.commandtype = commandtype.storedprocedure; //修改命令为执行存储过程!!!!!!
  10. parameters[3].direction = parameterdirection.returnvalue; //设置第四个参数为返回参数(为了测试方便就直接设置了)
  11. cmd.parameters.addrange(parameters); //添加参数
  12. cmd.executenonquery(); //执行存储过程!!!!!!!!
  13. int thereturn = (int)parameters[3].value; //接收返回值
  14. if (thereturn == 1) //bool类型在数据库为bit,返回值为 0 或 1
  15. {
  16. return true;
  17. }
  18. else
  19. {
  20. return false;
  21. }
  22. }
  23. }
  24. }
  public static bool executeprocedure(string procedurename, params sqlparameter[] parameters)          {              using (sqlconnection cOnn= new sqlconnection(connstr))              {                  conn.open();                  using (sqlcommand cmd = conn.createcommand())                  {                      cmd.commandtext = procedurename;                      cmd.commandtype = commandtype.storedprocedure;  //修改命令为执行存储过程!!!!!!                      parameters[3].direction = parameterdirection.returnvalue; //设置第四个参数为返回参数(为了测试方便就直接设置了)                      cmd.parameters.addrange(parameters); //添加参数                      cmd.executenonquery(); //执行存储过程!!!!!!!!                      int thereturn = (int)parameters[3].value;  //接收返回值                      if (thereturn == 1)  //bool类型在数据库为bit,返回值为 0 或 1                      {                          return true;                      }                      else                      {                          return false;                      }                  }              }          }

 

界面层中调用一个存储过程

private void btconfirm_click(object sender, routedeventargs e)

  1. {
  2. int fromid = int32.parse(txtfromid.text);
  3. int mOney= int32.parse(txtmoney.text);
  4. int toid = int32.parse(txttoid.text);
  5. bool issuccessed=false;
  6.  
  7. issuccessed = sqlhelper.executeprocedure("transferaccounts",
  8. new sqlparameter("@fromid", fromid),
  9. new sqlparameter("@money", money),
  10. new sqlparameter("@toid", toid),
  11. new sqlparameter("@issuccessed",0));
  12.  
  13. messagebox.show("" + issuccessed);
  14.  
  15. }
  private void btconfirm_click(object sender, routedeventargs e)          {              int fromid = int32.parse(txtfromid.text);              int mOney= int32.parse(txtmoney.text);              int toid = int32.parse(txttoid.text);              bool issuccessed=false;                issuccessed = sqlhelper.executeprocedure("transferaccounts",                  new sqlparameter("@fromid", fromid),                  new sqlparameter("@money", money),                  new sqlparameter("@toid", toid),                  new sqlparameter("@issuccessed",0));                messagebox.show("" + issuccessed);            }  

 

5.最后说下数据库可视化执行分页的存储过程

同样的,先创建

  1. create procedure paging (@pagesize int, @pageindex int) –参数:每页显示的行数,页数的索引
  2. as
  3. begin with temptable as(select row_number() over(order by id) as row, * from t_users) –临时表,按id排序,首列(row),记录所在行数
  4. select * from temptable where row between (@pageindex-1)*@pagesize + 1 and @pageindex*@pagesize
  5. end
  create procedure paging (@pagesize int, @pageindex int)  --参数:每页显示的行数,页数的索引   as   begin with temptable as(select row_number() over(order by id) as row, * from t_users)  --临时表,按id排序,首列(row),记录所在行数    select * from temptable where row between (@pageindex-1)*@pagesize + 1 and @pageindex*@pagesize   end

 

存储过程介绍以及使用(转账,分页)

 

本教程到此为止

需要了解更多数据库技术:存储过程介绍以及使用(转账,分页),都可以关注数据库技术分享栏目—编程笔记


推荐阅读
  • Oracle分析函数first_value()和last_value()的用法及原理
    本文介绍了Oracle分析函数first_value()和last_value()的用法和原理,以及在查询销售记录日期和部门中的应用。通过示例和解释,详细说明了first_value()和last_value()的功能和不同之处。同时,对于last_value()的结果出现不一样的情况进行了解释,并提供了理解last_value()默认统计范围的方法。该文对于使用Oracle分析函数的开发人员和数据库管理员具有参考价值。 ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • 微软头条实习生分享深度学习自学指南
    本文介绍了一位微软头条实习生自学深度学习的经验分享,包括学习资源推荐、重要基础知识的学习要点等。作者强调了学好Python和数学基础的重要性,并提供了一些建议。 ... [详细]
  • 电话号码的字母组合解题思路和代码示例
    本文介绍了力扣题目《电话号码的字母组合》的解题思路和代码示例。通过使用哈希表和递归求解的方法,可以将给定的电话号码转换为对应的字母组合。详细的解题思路和代码示例可以帮助读者更好地理解和实现该题目。 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 拥抱Android Design Support Library新变化(导航视图、悬浮ActionBar)
    转载请注明明桑AndroidAndroid5.0Loollipop作为Android最重要的版本之一,为我们带来了全新的界面风格和设计语言。看起来很受欢迎࿰ ... [详细]
  • 本文介绍了Linux系统中正则表达式的基础知识,包括正则表达式的简介、字符分类、普通字符和元字符的区别,以及在学习过程中需要注意的事项。同时提醒读者要注意正则表达式与通配符的区别,并给出了使用正则表达式时的一些建议。本文适合初学者了解Linux系统中的正则表达式,并提供了学习的参考资料。 ... [详细]
  • Android源码深入理解JNI技术的概述和应用
    本文介绍了Android源码中的JNI技术,包括概述和应用。JNI是Java Native Interface的缩写,是一种技术,可以实现Java程序调用Native语言写的函数,以及Native程序调用Java层的函数。在Android平台上,JNI充当了连接Java世界和Native世界的桥梁。本文通过分析Android源码中的相关文件和位置,深入探讨了JNI技术在Android开发中的重要性和应用场景。 ... [详细]
  • 3.223.28周学习总结中的贪心作业收获及困惑
    本文是对3.223.28周学习总结中的贪心作业进行总结,作者在解题过程中参考了他人的代码,但前提是要先理解题目并有解题思路。作者分享了自己在贪心作业中的收获,同时提到了一道让他困惑的题目,即input details部分引发的疑惑。 ... [详细]
  • 本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
  • 本文讨论了如何使用IF函数从基于有限输入列表的有限输出列表中获取输出,并提出了是否有更快/更有效的执行代码的方法。作者希望了解是否有办法缩短代码,并从自我开发的角度来看是否有更好的方法。提供的代码可以按原样工作,但作者想知道是否有更好的方法来执行这样的任务。 ... [详细]
author-avatar
手机用户2502905117
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有