一、什么是存储过程(Stored Procedure)

   存储过程是一段存储在数据库的“子程序”,本质是一个可重复使用的SQL代码块,可以理解为数据库端的“方法”。

   存储过程的好处:

    ①提高性能:由于数据库执行动作时,是先编译后执行的。然而存储过程是一个编译过的代码块,所以执行效率要比T-SQL语句高。

    ②提高通信速率:网络通信中传输的内容是存储过程名字,相比传输大量的sql语句网络的要通信量小,提高通信速率。

    ③提高安全性能:存储过程能够使没有权限的用户在控制之下间接地存取数据库,从而确保数据的安全。 

二、Sql Server使用存储过程

  例子使用的UserInfo表只有 UserName,UserPass,Email和主键 Id 列

2.1  简单的无参查询(查询用户名和密码)

  1. --创建查询用户名和密码的存储过程
  2. create proc pro_getUserList
  3. as
  4. select username,userpass from UserInfo
  5. go
  6.  
  7. --执行
  8. exec pro_getUserList

在C#中调用存储过程的代码

  1. using (SqlConnection conn = new SqlConnection(connStr))
  2. {
  3. SqlDataAdapter adapter = new SqlDataAdapter("pro_getUserList", conn);
  4. //设置CommandType
  5. adapter.SelectCommand.CommandType = CommandType.StoredProcedure;
  6. DataTable dt = new DataTable();
  7. //结果集存入dt中
  8. adapter.Fill(dt);
  9. //遍历显示结果集
  10. foreach (DataRow row in dt.Rows)
  11. {
  12. Console.WriteLine(row["username"]+"---"+row["userpass"]);
  13. }
  14. Console.ReadKey();
  15. }

2.2  有返回值的简单插入用户(插入一条新纪录,返回受影响的行数)

  1. --创建名为InsertUserInfo的存储过程
  2. create proc InsertUserInfo
  3. as
  4. insert into userinfo (username,userpass,email) values ('newuser','','123@qq.com')
  5. return @@rowcount
  6. go
  7.  
  8. --执行存储过程
  9. exec InsertUserInfo

在C#中调用存储过程的代码

  1. using (SqlConnection conn = new SqlConnection(connStr))
  2. {
  3. using (SqlCommand com=new SqlCommand("pro_insertUserInfo",conn))
  4. {
  5. conn.Open();
  6. com.CommandType = CommandType.StoredProcedure;//设置CommandType
  7. //创建一个接受返回值的参数,设置该参数是返回值类型
  8. SqlParameter par = new SqlParameter("count", SqlDbType.Int);
  9. par.Direction = ParameterDirection.ReturnValue;
  10. com.Parameters.Add(par);
  11.  
  12. int comResult = com.ExecuteNonQuery();//com.ExecuteNonQuery返回受影响的行数 1
  13. Console.WriteLine(comResult);
  14. Console.WriteLine(par.Value.ToString());//通过返回值获取受影响的行数 1
  15. Console.ReadKey();
  16. }
  17. }

2.3  有输入、输出、返回值的简单查询

  一个简单栗子:输入省份名查询该省的城市列表,out返回总的城市数目,retrun返回总的省份数目,栗子只是演示存储过程的结果接收方式,并没有太大的实际意义。

  注意一点 return参数必须是int类型的

  1. CREATE PROCEDURE [dbo].[proc_select_cities_by_provice]
  2. @provicename nvarchar(50),
  3. @citycount int out
  4. AS
  5. BEGIN
  6. SET NOCOUNT ON;
  7. --根据输入参数proviceName查询城市列表
  8. SELECT c.id cid,c.Name cname,p.Id pid,p.Name pname
  9. from Cities c join Provices p on c.ProviceId=p.Id where p.Name=@provicename;
  10.  
  11. --out返回城市的总数
  12. select @citycount=count(1) from Cities;
  13.  
  14. declare @provicecount int;
  15. select @provicecount=count(1) from Provices;
  16. --返回省份的总数
  17. return @provicecount;
  18. END
  19. GO

在C#中调用存储过程的代码

  1. static void Main(string[] args)
  2. {
  3. string connstr = "your sqlconnstring";
  4. using (SqlConnection conn = new SqlConnection(connstr))
  5. {
  6. conn.Open();
  7. using (SqlCommand com = conn.CreateCommand())
  8. {
  9. com.CommandText = "proc_select_cities_by_provice";
  10. com.CommandType = System.Data.CommandType.StoredProcedure;
  11.  
  12. SqlParameter[] pars = new SqlParameter[]
  13. {
  14. new SqlParameter("@provicename",System.Data.SqlDbType.NVarChar,){ Value="河南"},
  15. new SqlParameter("@citycount",System.Data.SqlDbType.Int){Direction=System.Data.ParameterDirection.Output},
  16. new SqlParameter("@provicecount",System.Data.SqlDbType.Int){Direction=System.Data.ParameterDirection.ReturnValue}
  17.  
  18. };
  19. com.Parameters.AddRange(pars);
  20. //接收城市列表
  21. using (SqlDataReader reader = com.ExecuteReader())
  22. {
  23. while (reader.Read())
  24. {
  25. Console.WriteLine(
  26. $"cid:{reader["cid"].ToString()}," +
  27. $"cname:{reader["cname"].ToString()}," +
  28. $"pid:{reader["pid"].ToString()}," +
  29. $"pname:{reader["pname"].ToString()}");
  30. }
  31. }
  32. //out参数输出
  33. Console.WriteLine($"out:{com.Parameters["@citycount"].Value.ToString()}");
  34. //return参数输出
  35. Console.WriteLine($"out:{com.Parameters["@provicecount"].Value.ToString()}");
  36. }
  37. }
  38. }
  39. }

2.4  返回多个结果集

  1. --返回多个结果集
  2. create proc pro_GetLists
  3. as
  4. select * from userInfo --取所有信息
  5. select username,userpass from UserInfo --只取用户名和密码
  6. go
  7.  
  8. --执行
  9. exec pro_GetLists

C#调用储存过程

  1. using (SqlConnection conn = new SqlConnection(connStr))
  2. {
  3. SqlDataAdapter adapter = new SqlDataAdapter("pro_GetLists", conn);
  4. DataSet ds = new DataSet();
  5. //ds中是所有的结果
  6. adapter.Fill(ds);
  7. DataTable dt0=ds.Tables[];//第一个select的结果集
  8. DataTable dt1 = ds.Tables[];//第二个select的结果集
  9. }

备注:在存储过程中return只能返回int类型,out(output)可以返回多种类型,执行到return的时候存储过程即结束,而out的变量可以重复设置。

     存储过程中的return和out参数值,在C#中都是通过参数来接收的,select的结果集可以用DataTable或者DataSet进行接收。

本文参考:

  1. http://www.cnblogs.com/knowledgesea/archive/2013/01/02/2841588.html
  2. https://blog.csdn.net/lengxiao1993/article/details/53427266
  3. http://www.cnblogs.com/aabbcc/p/6626372.html

Sqlserver中的储存过程的更多相关文章

  1. thinkphp调用sqlserver储存过程返回多个结果集

    首先安装扩展 windows 分为两个步骤 找到对应自己PHP版本的pdo扩展,下载解压出来,并且在php.ini里面启用扩展,需要注意的问题是php版本以及是否为安全版本 下载 ODBC Drive ...

  2. 我是如何在SQLServer中处理每天四亿三千万记录的

    首先声明,我只是个程序员,不是专业的DBA,以下这篇文章是从一个问题的解决过程去写的,而不是一开始就给大家一个正确的结果,如果文中有不对的地方,请各位数据库大牛给予指正,以便我能够更好的处理此次业务. ...

  3. SQLSERVER中的假脱机spool

    SQLSERVER中的假脱机spool 我发现网上对于假脱机的解释都非常零散,究竟假脱机是什么? 这几天在家里研究了一下,收集了很多网上的资料 假脱机是中文的翻译,而英文的名字叫做 spool 在徐老 ...

  4. 【转】我是如何在SQLServer中处理每天四亿三千万记录的

    原文转自:http://blog.jobbole.com/80395/ 首先声明,我只是个程序员,不是专业的DBA,以下这篇文章是从一个问题的解决过程去写的,而不是一开始就给大家一个正确的结果,如果文 ...

  5. (转)笔记320 SQLSERVER中的加密函数 2013-7-11

    1 --SQLSERVER中的加密函数 2013-7-11 2 ENCRYPTBYASYMKEY() --非对称密钥 3 ENCRYPTBYCERT() --证书加密 4 ENCRYPTBYKEY() ...

  6. SQLSERVER中的ALLOCATION SCAN和RANGE SCAN

    SQLSERVER中的ALLOCATION SCAN和RANGE SCAN 写这篇文章的开始,我还不知道ALLOCATION SCAN的工作原理是怎样的,网上资料少得可怜 求助了园子里的某位大侠,他看 ...

  7. XML 在SQLServer中的使用

    SQL Server对于XML支持的核心在于XML数据的格式,这种数据类型可以将XML的数据存储于数据库的对象中,比如variables, columns, and parameters.当你用XML ...

  8. C#函数与SQL储存过程

    一点点小认识作为memo,求指正. C#的函数与SQL的储存过程有很多的相似性, 它们都是一段封闭的代码块,来提高代码的重用性,虽然现在复制粘贴很方便,但是我们在写多个函数的时候频繁的复制粘贴相同的内 ...

  9. SQL获取所有数据库名、表名、储存过程以及参数列表

    SQL获取所有数据库名.表名.储存过程以及参数列表 1.获取所有用户名:SELECT name FROM Sysusers where status='2' and islogin='1'islogi ...

随机推荐

  1. linux下后台启动springboot项目

    linux下后台启动springboot项目 我们知道启动springboot的项目有三种方式: 运行主方法启动 使用命令 mvn spring-boot:run”在命令行启动该应用 运行“mvn p ...

  2. Python里format()方法基本使用

    '''第一种:自然连接''' #format 连接字符串 str = '{}使用的python是{}版本'.format('我','3.6.5') print(str) #打印结果:我使用的pytho ...

  3. mysql 0x80004005 unable to connect to any of the specified mysql hosts

    语言:c# 问题:偶尔会出现连不上mysql 报标题的这个错误. 解决方法:把server = localhost 改为 =127.0.0.1 或者静态IP  ,按着改暂时没出现了,继续观望!

  4. Leetcode 167. 两数之和 II - 输入有序数组 By Python

    给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数. 函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2. 说明: 返回的下标值 ...

  5. hexo从零开始

    部署Hexo Hexo官方文档 新建一个文件夹,比如,Blog,然后进入该文件夹下: npm install hexo-cli -g hexo version 安装依赖包 npm install 配置 ...

  6. W10笔记本电脑弄成WIFI

    用网线连接的笔记本弄成WIFI供手机上网.以前是买了一个随身 WIFI,可以当网卡使用.后来使用命令 // 建立WIFI netsh wlan set hostednetwork mode=allow ...

  7. <Android基础>(二) Activity Part 1

    1.活动的基本用法: 1) 手动创建活动.创建加载布局 2) 在AndroidManifest文件中注册 3) 在活动中添加Button.Toast.Menu 4) 销毁活动 2.Intent 1) ...

  8. HDU--4486 Task(贪心)

    题目链接  4486 Task 按照时间从大到小排序 然后枚举所有的y值 用一个数组存储 符合要求就算上 #include<bits/stdc++.h> using namespace s ...

  9. 洛谷P4248 差异

    题意:求所有后缀两两之间的最长公共前缀的长度之和. 解:这道题让我发现了一个奇妙的性质:所有后缀两两最长公共前缀长度之和 和 所有前缀两两最长公共后缀之和的值是相等的,但是每一组公共前/后缀是不同的. ...

  10. n+lognlogV查找最大值

    来自Blogewoosh #6. 啃了一下,写个翻译吧. 问题:你有一个数组,你不知道每个元素的大小,但是能够提出询问:a[x]是否>=v?你需要找出这个数组的最大值,只能询问n + lognl ...