第七天 -- 《2014-07-14 SQL进阶》1 -- 存储过程

一、上午《02、存储过程的概念》

1、存储过程---就像数据库中运行方法(函数)

  和C#里的方法一样,由存储过程名、存储过程参数组成 ,可以有返回结果。
前面学的if else/while/变量/insert/select 等,都可以在存储过程中使用

(1)优点:
  执行速度更快 – 在数据库中保存的存储过程SQL语句都是编译过的
  允许模块化程序设计 – 类似方法的复用
  提高系统安全性 – 防止SQL注入
  减少网络流通量 – 只要传输 存储过程的名称

(2)系统存储过程
  由系统定义,存放在master数据库中
  名称以“sp_”开头或”xp_”开头。
(3)自定义存储过程
  由用户在自己的数据库中创建的存储过程。一般以usp_开头。

 

二、上午《03、第一个存储过程的创建》--《04、创建有多个形参的存储过程》

1、创建存储过程

--(1)创建存储过程:
--go
--create procedure  usp_存储过程名称
--(形参) 可以以这个里面声明参数
--as  --相当于方法体开始
---- 自定义局部变量
---- 逻辑语句sql、事务、调用其他存储过程等
--go

--(2)调用存储过程:

--execute  存储过程名  [参数列表,...]

例子如下:

 1 --例一:查询所有学员信息
 2 if exists(select * from sysobjects where name='usp_getAllStuInfo')
 3     drop proc usp_getAllStuInfo
 4 go
 5 --创建存储过程,上面如果已存在就删除它
 6 create procedure usp_getAllStuInfo
 7 as
 8     select * from Student
 9 go
10 
11 --调用存储过程,获取所有学员信息
12 exec usp_getAllStuInfo
13 
14 --例二:查询指定性别的学员信息
15 if exists(select * from sysobjects where name='usp_getAllStuInfoBySex')
16     drop proc usp_getAllStuInfoBySex
17 go
18 
19 create procedure usp_getAllStuInfoBySex
20     @sex  char(2)     --形参不能用declare
21 as
22 select * from Student where Sex=@sex
23 go
24 
25 --调用存储过程。返回指定性别的学员信息
26 exec usp_getAllStuInfoBySex  'dafgfhghj'  
27 --注意存储过程参数为char(2),只截取前两个字节(此例为‘da’,如果参数输入Unicode的‘女人’,就只截取‘女’)
28 
29 
30 --例三:获取指定性别和班级名称的学员信息
31 if exists(select * from sysobjects where name='usp_getAllStuInfoBySexAndClassName')
32     drop proc usp_getAllStuInfoBySexAndClassName
33 go
34 create proc usp_getAllStuInfoBySexAndClassName
35  @sex char(2),                        --注意逗号别忘
36  @className nvarchar(50) 
37 as
38  declare @classId int --局部变量:科目 ID
39  set @classId=(select classid from grade where classname=@className) 
40  select * from Student where Sex=@sex and ClassId=@classId
41 go
42 
43 --调用存储过程,返回指定班级名称和性别的学员信息
44 exec usp_getAllStuInfoBySexAndClassName  '',  '七期班'

 

2、存储过程注意点

  (1)调用存储传入参数时,可以传入可转换的值。

    比如形参要求字符串,你除了可以传入字符串外,其实可以传入任何值。因为它们都可以转字符串。

    假如形参要求数值,你就应该传入数值,若传入数值字符串也不会错(因为可转换),但如果传入其他字符串无法转为数值时,会报错。

  (2)若参数定义为字符串(可变或不可变),传入超长字符串,会按(参数定义)要求的长度截取前N个字符。不会报错。

       (3)注意区分Unicode和非Unicode数据类型,前者1个字符占2字节,后者1个字符占1字节

 

 

三、上午《05、创建有默认值参数的存储过程》

1、默认参数和C#中概念类似

--参数传递次序要一致:第一个实参默认就是传递给第一个形参... 以此类推
--如果形参定义了默认值,那么调用存储过程时可以写default代表使用默认值
--也可以使用 @参数 = 值 的方式调用存储过程,这样就与顺序没有关系了。
--一旦使用了 @name = value  形式之后,所有后续的参数就必须以  @name = value  的形式传递。前面的参数没有限制

如下例:

 1 --创建有默认值的存储过程
 2 if exists(select * from sysobjects where name='usp_getAllStuInfoBySexAndClassName')
 3    drop proc usp_getAllStuInfoBySexAndClassName
 4 go
 5 create proc usp_getAllStuInfoBySexAndClassName
 6    @sex char(2)='',     --往往会将有默认值的参数写在所有参数列表的最后,调用的时候比较方便。
 7    @className nvarchar(50) 
 8 as
 9    declare @classId int --科目 ID
10    set @classId=(select classid from grade where classname=@className) 
11    select * from Student where Sex=@sex and ClassId=@classId
12 go
13 
14 --调用存储过程
15 exec usp_getAllStuInfoBySexAndClassName  @className='七期班', @sex=''   --类似具名实参,就和次序无关了

 

 

四、上午《06、创建带输出参数的存储过程》--《07、创建有返回值的存储过程》

1、带输出参数的存储过程

注意:声明形参的时候要加上output;调用存储过程的时候也要加output

 1 --根据班级和性别查询学员,同时返回总人数和指定性别的人数
 2 if exists(select * from sysobjects where name='usp_getSInfoAndCount')
 3     drop proc usp_getSInfoAndCount
 4 go
 5 create proc  usp_getSInfoAndCount
 6  @totalNum int output,          --指定班级的总人数
 7  @claNum int output,             --指定班级和性别的总人数
 8  @ClassName nvarchar(50),  --输入参数:需要用户传入值
 9  @sex char(2)='' 
10 as
11     declare @cid int = (select classid from grade where classname=@ClassName) --根据班级名称获取班级ID
12     select * from Student where ClassId=@cid and Sex=@sex
13     set @totalNum=(select COUNT(*) from Student )--总人数
14     set @claNum =(select COUNT(*) from Student where ClassId=@cid and Sex=@sex)
15 go
16 
17 --调用在输出参数的存储过程
18 declare @tnum int, @cnum int    --声明变量用来接收输出参数的值
19 exec usp_getSInfoAndCount @ClassName='七期班' ,@totalNum=@tnum output, @claNum=@cnum output
20 print @tnum
21 print @cnum

 

2、有返回值的存储过程

注意(1)return只能反回整数值。所以需要从存储过程中返回结果的,多使用output参数

  (2)调用存储过程时要用 exec @变量 = 存储过程名 参数    的形式来调用。

 1 ---返回指定人数
 2 if exists(select * from sysobjects where name='usp_getNameByNo')
 3    drop proc usp_getNameByNo
 4 go
 5 create proc usp_getNameByNo
 6    @cid int        --指定班级ID
 7 as
 8  declare @cnt int 
 9  set @cnt = (select COUNT(*) from Student where ClassId=@cid) 
10 
11  return @cnt --return只能返回 整数值
12 go
13 
14 --调用存储过程,返回指定学号的学员名字
15 declare @count int 
16 exec @count= usp_getNameByNo  6
17 print @count

 

 

五、下午《01、C#使用存储过程的大致方式》--《04、调用有输出参数的存储过程》

1、ADO.NET使用DataAdapter调用存储过程

注意:调用有参数的存储过程时,DataAdapter.SelectCommand.CommandType要设置为 StoredProcedure

1 //调用无参存储过程“usp_getAllStuInfo”
2 SqlDataAdapter da = new SqlDataAdapter("usp_getAllStuInfo", connStr);
3 DataTable dt = new DataTable();
4 da.Fill(dt);
5 this.dgvList.DataSource = dt;
 1 //调用有参数的存储过程
 2 SqlDataAdapter da = new SqlDataAdapter("usp_getAllStuInfoBySex", connStr);
 3 //1.确定命令的类型是存储过程:你得告诉服务器这是存储过程.有参数的时候就必须设置命令的类型
 4 da.SelectCommand.CommandType = CommandType.StoredProcedure;
 5 //2.声明定义参数
 6 SqlParameter p = new SqlParameter("@sex", "");
 7 //3.将参数添加到数据适配器的SelectCommand对象中
 8 da.SelectCommand.Parameters.Add(p);
 9 DataTable dt = new DataTable();
10 da.Fill(dt);
11 this.dgvList.DataSource = dt;

 

2、调用有输出参数和返回值的存储过程

注意,输出参数和返回值都需要设置SQLParameter

 1 SqlDataAdapter da = new SqlDataAdapter("usp_getSInfoAndCount", connStr);
 2 //1.指定命令类型:
 3 //Text=An SQL text command. (Default.);StoredProcedure=The name of a stored procedure.;TableDirect=The name of a table.
 4 da.SelectCommand.CommandType = CommandType.StoredProcedure;
 5 
 6 //2.创建存储过程中对应的参数
 7 SqlParameter[] ps = { 
 8                     new SqlParameter("@ClassName", “十四期班”),
 9                     //2.1对于输出参数和返回值,当然不是给值,而是确定数据类型
10                     new SqlParameter("@totalNum", SqlDbType.Int),
11                     new SqlParameter("@claNum", SqlDbType.Int),
12                     new SqlParameter("@sex",  ""),
13                     new SqlParameter("cnt", SqlDbType.Int)
14                     };
15 //3.将参数添加到命令对象中
16 da.SelectCommand.Parameters.AddRange(ps);
17 
18 //4.对于 output参数,一定需要设置参数的方向
19 ps[0].Direction = ParameterDirection.Input; //默认值此值--输入参数
20 //如果参数的方向是output,那么就说明它是向服务器请求参数中对应名称的变量值。那么服务器就会将对应的变量值返回存储到参数对象的Value属性中
21 ps[1].Direction = ParameterDirection.Output;
22 ps[2].Direction = ParameterDirection.Output;
23 ps[3].Direction = ParameterDirection.Input;
24 //返回值,要设置为ReturnValue
25 ps[4].Direction = ParameterDirection.ReturnValue;
26 
27 DataTable dt = new DataTable();
28 da.Fill(dt);
29 this.dgvList.DataSource = dt;
30 //显示存储过程的输出参数和返回值
31 MessageBox.Show(ps[1].Value + "  " + ps[2].Value + "  " + ps[4].Value);

 

posted on 2017-07-27 13:34  困兽斗  阅读(259)  评论(0)    收藏  举报

导航