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

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

   存储过程的好处:

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

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

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

二、Sql Server使用存储过程

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

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

--创建查询用户名和密码的存储过程
create proc pro_getUserList
as
select username,userpass from UserInfo
go --执行
exec pro_getUserList

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

using (SqlConnection conn = new SqlConnection(connStr))
{
SqlDataAdapter adapter = new SqlDataAdapter("pro_getUserList", conn);
//设置CommandType
adapter.SelectCommand.CommandType = CommandType.StoredProcedure;
DataTable dt = new DataTable();
//结果集存入dt中
adapter.Fill(dt);
//遍历显示结果集
foreach (DataRow row in dt.Rows)
{
Console.WriteLine(row["username"]+"---"+row["userpass"]);
}
Console.ReadKey();
}

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

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

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

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

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

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

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

CREATE PROCEDURE [dbo].[proc_select_cities_by_provice]
@provicename nvarchar(50),
@citycount int out
AS
BEGIN
SET NOCOUNT ON;
--根据输入参数proviceName查询城市列表
SELECT c.id cid,c.Name cname,p.Id pid,p.Name pname
from Cities c join Provices p on c.ProviceId=p.Id where p.Name=@provicename; --out返回城市的总数
select @citycount=count(1) from Cities; declare @provicecount int;
select @provicecount=count(1) from Provices;
--返回省份的总数
return @provicecount;
END
GO

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

        static void Main(string[] args)
{
string connstr = "your sqlconnstring";
using (SqlConnection conn = new SqlConnection(connstr))
{
conn.Open();
using (SqlCommand com = conn.CreateCommand())
{
com.CommandText = "proc_select_cities_by_provice";
com.CommandType = System.Data.CommandType.StoredProcedure; SqlParameter[] pars = new SqlParameter[]
{
new SqlParameter("@provicename",System.Data.SqlDbType.NVarChar,){ Value="河南"},
new SqlParameter("@citycount",System.Data.SqlDbType.Int){Direction=System.Data.ParameterDirection.Output},
new SqlParameter("@provicecount",System.Data.SqlDbType.Int){Direction=System.Data.ParameterDirection.ReturnValue} };
com.Parameters.AddRange(pars);
//接收城市列表
using (SqlDataReader reader = com.ExecuteReader())
{
while (reader.Read())
{
Console.WriteLine(
$"cid:{reader["cid"].ToString()}," +
$"cname:{reader["cname"].ToString()}," +
$"pid:{reader["pid"].ToString()}," +
$"pname:{reader["pname"].ToString()}");
}
}
//out参数输出
Console.WriteLine($"out:{com.Parameters["@citycount"].Value.ToString()}");
//return参数输出
Console.WriteLine($"out:{com.Parameters["@provicecount"].Value.ToString()}");
}
}
}
}

2.4  返回多个结果集

--返回多个结果集
create proc pro_GetLists
as
select * from userInfo --取所有信息
select username,userpass from UserInfo --只取用户名和密码
go --执行
exec pro_GetLists

C#调用储存过程

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

备注:在存储过程中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. Codeforces Round #543 (Div. 2, based on Technocup 2019 Final Round)

    A. Technogoblet of Fire 题意:n个人分别属于m个不同的学校 每个学校的最强者能够选中 黑客要使 k个他选中的可以稳被选 所以就为这k个人伪造学校 问最小需要伪造多少个 思路:记 ...

  2. Java异步、线程池解决方案

    一.ThreadPoolExecutor------线程池 private static final ThreadPoolExecutor threadPoolExecutor = new Threa ...

  3. 【BZOJ1013】【JSOI2008】球形空间产生器 高斯消元

    题目描述 有一个\(n\)维空间中的球,告诉你球面上\(n+1\)个点的坐标,求球心的坐标. \(n\leq 10\) 题解 设\(a_{i,j}\)为第\(i\)个点的第\(j\)维坐标,\(i=0 ...

  4. Codeforces Round #530 (Div. 2) F (树形dp+线段树)

    F. Cookies 链接:http://codeforces.com/contest/1099/problem/F 题意: 给你一棵树,树上有n个节点,每个节点上有ai块饼干,在这个节点上的每块饼干 ...

  5. 【转】C++命名空间 namespace的作用和使用解析

    一. 为什么需要命名空间(问题提出) 命名空间是ANSIC++引入的可以由用户命名的作用域,用来处理程序中 常见的同名冲突. 在 C语言中定义了3个层次的作用域,即文件(编译单元).函数和复合语句.C ...

  6. bzoj3959(LCT)

    题目描述 某校开展了同学们喜闻乐见的阳光长跑活动.为了能“为祖国健康工作五十年”,同学们纷纷离开寝室,离开教室,离开实验室,到操场参加3000米长跑运动.一时间操场上熙熙攘攘,摩肩接踵,盛况空前. 为 ...

  7. NOIP2011Mayan游戏(模拟)

    Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个77 行\times 5×5列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上.游戏通关是指 ...

  8. HDU--1540 Tunnel Warfare(线段树区间更新)

    题目链接:1540 Tunnel Warfare 以为单组输入 这个题多组输入 结构体记录每个区间左边和右边的连续区间 ms记录最大 在查询操作时: 1.这个点即将查询到右区间 看这个点 x 是否存在 ...

  9. Android 架构 -- Room

    gradle依赖: // add for room implementation "android.arch.persistence.room:runtime:1.1.1" // ...

  10. VS Code汉化

    F1搜索  Configure Language { // Defines VS Code's display language. // See https://go.microsoft.com/fw ...