最初接触存储过程是在耿建玲老师的视频里,当初仅仅是草草过了一遍。仅仅是有了个印象。知道了这个名词;大二时也有SqlServer数据库这门课,只是老师没讲,自己也没看;真正对存储过程的了解来自于自学考试中的《数据库系统原理》,在考试中,知道存储过程是干嘛的。在纸上怎么写,但从来没有在DBMS中亲手敲过。于是机房收费系统给了我这个机会。

       在这里不再过多叙述关于存储过程德基本知识,仅仅写一下在机房收费系统这个小项目中是怎样用到存储过程的。

       背景:

       机房收费系统中有一个注冊的功能,原型图例如以下:

       

        

        注冊时。须要对数据库中的三个表进行更新(向卡表T_Card、学生表T_Student、充值表T_Register中分别新增一条记录),所以,运行时,假设用运行SQL语句的方式,那就须要运行三次SQL语句:

        1:向卡表T_Card加入记录

insert into T_Card(cardNumber ,balance ,type ,stuNumber ,status ,isChecked ) values(@cardNumber ,@balance, @type ,@stuNumber ,@status ,@isChecked )

        2:向学生表T_Student加入记录

insert into T_Student (stuNumber,stuName,stuSex,stuMajor,stuGrade,stuClass ,comment ) values (@stuNumber ,@stuName ,@stuSex ,@stuMajor ,@stuGrade ,@stuClass,@comment )

        3:向充值表T_Register加入记录

insert into chargesystem.dbo.T_Recharge (userID,cardNumber,rechargeCash ,rechargeDate ,rechargeTime ,isChecked )values(@userID,@cardNumber ,@balance, CONVERT(varchar,getdate(),120),CONVERT(varchar,GETDATE(),108),'未结账')

        存储过程的使用

        对于上面的需求,假设用存储过程,在数据库里建立存储过程之后,在代码里仅仅需负责直接运行这个存储过程就可以,而不用连续多次连接、操作数据库。

       

一、建立存储过程

        建立存储过程有两种方法(由于系统用的数据库为SqlServer2008,所以这里以此为例):

        (1)、手动建立存储过程:

        对象资源管理器中:数据库→ChargeSystem(数据库名称)→可编程性→右键“存储过程”→新建存储过程

         

        新建的存储过程能够说是一个已经成型的存储过程德模板。我们仅仅需在上面改动一下存储过程名称、參数、运行语句等代码就OK了。     

       (2)、SQL语句加入存储过程

        直接新建查询。在代码编辑窗体编写存储过程SQL代码,基本的语法为:

         CREATE  PROCEDURE  PROC_NAME

               @[參数名] [类型],@[參数名] [类型]……

         AS

         BEGIN

               [过程体].........

         END

         用第一种方法建立的存储过程基本上也是这个结构。增加对应的參数和过程体之后,完整的存储过程为:

        

CREATE PROCEDURE PROC_Register

-- 定义參数

@cardNumber varchar(6),@balance decimal(5,1),@type nvarchar(20),@status nvarchar(50),@isChecked nvarchar(10),

@stuNumber varchar(18),@stuName nvarchar(10),@stuSex varchar(6),@stuMajor nvarchar(30),@stuGrade nvarchar(20),@stuClass nvarchar(20),@comment nvarchar(100),

@userID varchar(18)

AS

BEGIN

--向表中插入数据

insert into ChargeSystem .dbo.T_Card(cardNumber ,balance ,type ,stuNumber ,status ,isChecked ) values(@cardNumber ,@balance, @type ,@stuNumber ,@status ,@isChecked )

insert into ChargeSystem .dbo.T_Student (stuNumber,stuName,stuSex,stuMajor,stuGrade,stuClass ,comment ) values (@stuNumber ,@stuName ,@stuSex ,@stuMajor ,@stuGrade ,@stuClass,@comment )

insert into chargesystem.dbo.T_Recharge (userID,cardNumber,rechargeCash ,rechargeDate ,rechargeTime ,isChecked )values(@userID,@cardNumber ,@balance, CONVERT(char(10),getdate(),120),CONVERT(varchar,GETDATE(),108),'未结账')

END

            注意:不管是用哪种方式建立的存储过程。都须要点击运行来存到server里。才干够通过以后的调用来运行,单纯地保存(ctrl+C)仅仅是把这个存储过程文件保存在本地,而不会存入数据库server中。

       当建立好存储过程时,能够新建查询运行“exec 存储过程名 @參数1=值1,@參数2=值2……”来验证存储过程是否正确。

        二、代码中调用存储过程

        调用存储过程跟运行SQL语句的方式大同小异,须要注意的是,运行SQL语句时。命令对象Command的CommandType的值为CommandType.Text,而运行存储过程时。CommandType的值为CommandType.StoredProcedure。

        在本例中详细代码为:

        D层代码:       

Public Class SqlServerRegisterDAL : Implements IDAL.IRegister

Public Function Insert(ByVal enCard As Entity.CardEntity, ByVal enStudent As Entity.StudentEntity, ByVal userID As String) As Boolean Implements IDAL.IRegister.Insert

Dim sqlHelper As New SqlHelper '定义SqlHelper实例

Dim cmdType As CommandType = CommandType.StoredProcedure '定义数据库命令类型

Dim cmdText As String = "PROC_Register" '数据库运行字符串

Dim parameters As SqlParameter() '定义參数数组,负责向存储过程中的变量传值

'为參数数组中的參数一一赋值

parameters = {New SqlParameter("@cardNumber", enCard.CardNumber), New SqlParameter("@balance", enCard.Balance),

New SqlParameter("@type ", enCard.CardType), New SqlParameter("@status", enCard.Status),

New SqlParameter("@isChecked", enCard.IsChecked), New SqlParameter("@stuNumber", enStudent.StuNumber),

New SqlParameter("@stuName", enStudent.StuName), New SqlParameter("@stuSex", enStudent.StuSex),

New SqlParameter("@stuMajor", enStudent.StuMajor), New SqlParameter("@stuGrade", enStudent.StuGrade),

New SqlParameter("@stuClass", enStudent.StuClass), New SqlParameter("@comment", enStudent.StuComment),

New SqlParameter("@userID", userID)}

'推断是否有查询结果

If sqlHelper.ExecuteNonQuery(cmdText, cmdType, parameters) Then

Return True

Else

Return False

End If

End Function

End Class

        SqlHelper代码:

Public Class SqlHelper

'从配置文件里获取连接字符串的值

Dim strConnection As String = ConfigurationSettings.AppSettings("strConnection")

'创建数据库连接对象conn

Dim conn As SqlConnection

'创建数据库操作类cmd

Dim cmd As New SqlCommand

'''

''' 构造函数,实例化类时就初始化数据库连接对象

'''

'''

Public Sub New()

conn = New SqlConnection(strConnection)

End Sub

'''

''' 关闭释放SqlCommand对象

'''

''' 须要关闭的SqlCommand对象

''' cmd.Dispose()直接释放command资源,不知这么做对系统性能怎么样,先这么着,以后再继续优化

Public Sub CloseCommand(ByVal cmd As SqlCommand)

If Not IsNothing(cmd) Then

cmd.Dispose()

cmd = Nothing

End If

End Sub

'''

''' 关闭数据库连接

'''

''' 须要关闭的SqlConnection对象

''' 关闭数据库连接。但并没有释放,而是存储在连接池中。须要的时候还能够通过Open()方法打开连接

Public Sub CloseConnection(ByVal conn As SqlConnection)

If Not IsNothing(conn) Then

conn.Close()

End If

End Sub

'''

''' 有參数的 增 删 改 操作

'''

''' 须要运行的SQL命令

''' 所运行命令的。通常是sql语句、存储过程或表

''' 參数数组

''' 返回受影响的行数 类型为整型

'''

Public Function ExecuteNonQuery(ByVal cmdText As String, ByVal cmdType As String, ByVal sqlParameters As SqlParameter()) As Integer

Try

conn.Open() '打开数据库连接

cmd.CommandText = cmdText '设置查询语句

cmd.CommandType = cmdType '设置一个值,解释cmdType(假设值为StoredProcedure时。调用的是存储过程)

cmd.Connection = conn '设置连接

cmd.Parameters.AddRange(sqlParameters) '传入參数

Dim affectedRows As Integer

affectedRows = cmd.ExecuteNonQuery

Return affectedRows '返回运行所受影响行数

Catch ex As Exception

MsgBox(ex.Message, MsgBoxStyle.OkOnly, "温馨提示")

Return 0 '假设出错,则返回0

Finally

cmd.Parameters.Clear() '清楚參数

Call CloseCommand(cmd) '关闭并释放Command

Call CloseConnection(conn) '关闭连接conn

End Try

End Function

End Class

      为什么要使用存储过程

      

       注冊学生卡号在这个系统中不算个大模块,但这个小小的需求。须要与数据库中三个表的数据打交道。而在以往的操作,居然连了三次数据库。运行了三次SQL语句。

       这样频繁地打开与关闭与数据库的连接。须要消耗大量系统资源,减少运行速度。这时就须要考虑用存储过程来取代运行如此之多的SQL语句。

       1、一般SQL语句每运行一次就须要编译一次,而存储过程仅仅是在创造时进行编译,以后每次运行都不须要再进行编译。

       2、存储过程就是相当于把多个须要运行的SQL语句集合起来,变成一条SQL语句,当然就仅仅需连接和运行一次就能够得到结果。

       3、安全性高。能够指定存储过程的使用权,防止SQL注入。

       4、系统升级、维护比較方便。

       总结:

       ★ 当涉及到多个SQL语句运行,须要多次连接数据库。或者须要对多张表进行处理时,能够将这些操作封装在一起,即创建存储过程。以后每次须要的时候直接调用运行。就可以运行全部的操作,避免了多次打开、关闭数据库连接。

       ★ 当涉及到比較复杂的需求时(比方机房收费系统中的下机结算消费金额就能够採用存储过程)。比方排序、计算等等。能够把数据直接传到存储过程,一系列操作在数据库server里进行,减小了client与server之间的数据流量,同一时候还保证了系统的安全性。

  

       到了这里大家脑子里可能会有个问题:既然让一个存储过程运行多个任务,那么万一在运行的过程中,这些任务中的一个或者几个任务没有完毕。该怎样是好?这时事务就派上用场了…快去实践吧…

       

        

查看原文