SQLSever视图和存储过程
一.视图(View)
1. 为什么要学习视图?
在没有视图之前,我们都是写各种各样的SQL语句,有点,非常灵活。后面我们学习应用程序开发的时候,通过C#发送过来的SQL语句
到达数据库的时候,会执行什么过程呢?
数据库接收到各种应用程序发送的SQL语句的时候,通常的流程是这样的:
【1】语法检查-->【2】优化(根据你的查询条件内容,和索引情况等,综合优化一下)-->【3】编译-->【4】执行
我们想,常见的查询,尤其是组合查询,能不能把查询固化到数据库服务器端,然后客户端使用的时候,只是调用一下呢?
当然可以,这个就是我们要学习的存储过程和视图。
视图其实就是一个查询,本身没有数据,就是把我们要查询的SQL语句,经过优化后经过编译存储到数据库服务器端。
视图我们本身也可以把它看成一个“没有数据的表”。
2.视图的创建与使用。这里提前创建了一个CourseManageDB数据库
use CourseManageDB
go
--普通查询
select CourseId,CourseName,CourseContent,ClassHour,Credit,Course.CategoryId from Course inner join CourseCategory on Course.CategoryId=CourseCategory.CategoryId;
--把上述查询添加到视图中
if exists(select * from sysobjects where name='queryCourseInfo_view')
drop view queryCourseInfo_view
go
--创建视图
create view queryCourseInfo_view
as
select CourseId,CourseName,CourseContent,ClassHour,Credit,Course.CategoryId from Course inner join CourseCategory on Course.CategoryId=CourseCategory.CategoryId;
go
--视图创建好后,我们可以把它看成表一样查询
select * from queryCourseInfo_view where CourseId>1005;
--实际开发中,可能会比较复杂:case when
--创建一个复杂的视图
if exists(select * from sysobjects where name='queryCourseInfo_view2')
drop view queryCourseInfo_view2
go
create view queryCourseInfo_view2
as
select Course.CategoryId,CourseId,CourseName,CourseContent,Credit,TeacherId,CategoryName,ClassHour=case
when ClassHour>400 then 500
when ClassHour<400 then 400
else
300
end
from Course inner join CourseCategory
on Course.CategoryId=CourseCategory.CategoryId;
go
--使用视图
select * from queryCourseInfo_view2;
在C#中调用视图,视图的查询和查询表一样,把表名换成视图名称即可。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Models;
using System.Configuration;
using System.Data;
using System.Data.SqlClient; namespace DAL
{
/// <summary>
/// 通用数据访问类
/// </summary>
[Serializable]
public class SQLHelper
{
private static string connString = ConfigurationManager.ConnectionStrings["connString"].ToString();
/// <summary>
/// 通用增删改方法
/// </summary>
/// <param name="cmdText">查询语句</param>
/// <param name="param">参数数组</param>
/// <param name="IsProcedure">判断是否是存储过程</param>
/// <returns>返回受影响的行数</returns>
public static int Update(string cmdText, SqlParameter[] param = null, bool IsProcedure = false)
{
SqlConnection conn = new SqlConnection(connString);
SqlCommand cmd = new SqlCommand(cmdText, conn);
try
{
conn.Open();
if (param != null)
{
cmd.Parameters.AddRange(param);
}
if (IsProcedure == true)
{
cmd.CommandType = CommandType.StoredProcedure;
}
return cmd.ExecuteNonQuery();
}
catch (Exception)
{
throw;
}
finally
{
conn.Close();
}
} /// <summary>
/// 启用事务来执行多条sql语句
/// </summary>
/// <param name="listSql"></param>
/// <returns></returns>
public static bool UpdateByTrans(List<string> listSql)
{
SqlConnection conn = new SqlConnection(connString);
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
try
{
conn.Open();
cmd.Transaction = conn.BeginTransaction();//开启事务
foreach (string sql in listSql)
{
cmd.CommandText = sql;
cmd.ExecuteNonQuery();
}
cmd.Transaction.Commit();//提交事务(提交后会自动清除事务)
return true;
}
catch (Exception ex)
{
if (cmd.Transaction != null)
cmd.Transaction.Rollback();//执行某一条sql语句时出错,回滚事务(回滚事务后会自动清除事务)
cmd.Transaction = null;//清楚事务
throw ex;
}
finally
{
//为了以防万一,最后加一条判断,清除事务
if (cmd.Transaction != null)
cmd.Transaction = null;
conn.Close();
} } /// <summary>
///查询单条数据
/// </summary>
/// <param name="cmdText">查询语句</param>
/// <param name="param">参数数组</param>
/// <param name="IsProcedure">判断是否是存储过程</param>
/// <returns>返回单条数据查询结果</returns>
public static object GetSingleResult(string cmdText, SqlParameter[] param = null, bool IsProcedure = false)
{
SqlConnection conn = new SqlConnection(connString);
SqlCommand cmd = new SqlCommand(cmdText, conn);
try
{
conn.Open();
if (param != null)
{
cmd.Parameters.AddRange(param);
}
if (IsProcedure == true)
{
cmd.CommandType = CommandType.StoredProcedure;
}
return cmd.ExecuteScalar();//可以执行一个增删改语句的同时再执行一个查询语句(比如添加,再查询添加的标识列)
}
catch (Exception)
{
throw;
}
finally
{
conn.Close();
}
} /// <summary>
///返回查询结果集
/// </summary>
/// <param name="cmdText">查询语句</param>
/// <param name="param">参数数组</param>
/// <param name="IsProcedure">判断是否是存储过程</param>
/// <returns>返回查询结果集</returns>
public static SqlDataReader GetReader(string cmdText, SqlParameter[] param = null, bool IsProcedure = false)
{
SqlConnection conn = new SqlConnection(connString);
SqlCommand cmd = new SqlCommand(cmdText, conn);
try
{
conn.Open();
if (param != null)
{
cmd.Parameters.AddRange(param);
}
if (IsProcedure == true)
{
cmd.CommandType = CommandType.StoredProcedure;
}
return cmd.ExecuteReader(CommandBehavior.CloseConnection);//reader关闭,conn也将关闭(conn关闭,reader将读取不到数据,会报错)
}
catch (Exception)
{
throw;
}
} /// <summary>
/// 基于DataSet来实现数据的查询(视图的操作类似于表)
/// </summary>
/// <param name="cmdText">查询语句或者存储过程</param>
/// <param name="param">参数数组</param>
/// <param name="IsProCedure">是否是存储过程</param>
/// <param name="tableName">给表起的名</param>
/// <returns>返回查询到的表数据</returns>
public static DataSet GetTableData(string cmdText, bool IsProCedure = false, string tableName = null, SqlParameter[] param = null)
{
SqlConnection conn = new SqlConnection(connString);
SqlCommand cmd = new SqlCommand(cmdText, conn);
try
{
conn.Open();
if (param != null)
{
cmd.Parameters.AddRange(param);
}
if (IsProCedure == true)
{
cmd.CommandType = CommandType.StoredProcedure;
}
//创建数据适配器
SqlDataAdapter da = new SqlDataAdapter(cmd);
//创建数据集对象
DataSet ds = new DataSet();
if (tableName != null)
{
da.Fill(ds, tableName);
}
else
{
da.Fill(ds);
}
return ds;
}
catch (Exception)
{
throw;
}
} /// <summary>
/// 获取系统时间
/// </summary>
/// <returns></returns>
public static DateTime GetTime()
{
return Convert.ToDateTime(SQLHelper.GetSingleResult("select getdate()"));
}
}
}
/// <summary>
/// 基于DataSet来实现数据的查询(视图的操作类似于表)
/// </summary>
/// <param name="cmdText">查询语句或者存储过程</param>
/// <param name="param">参数数组</param>
/// <param name="IsProCedure">是否是存储过程</param>
/// <param name="tableName">给表起的名</param>
/// <returns>返回查询到的表数据</returns>
public static DataSet GetTableData(string cmdText, bool IsProCedure = false, string tableName = null, SqlParameter[] param = null)
{
SqlConnection conn = new SqlConnection(connString);
SqlCommand cmd = new SqlCommand(cmdText, conn);
try
{
conn.Open();
if (param != null)
{
cmd.Parameters.AddRange(param);
}
if (IsProCedure == true)
{
cmd.CommandType = CommandType.StoredProcedure;
}
//创建数据适配器
SqlDataAdapter da = new SqlDataAdapter(cmd);
//创建数据集对象
DataSet ds = new DataSet();
if (tableName != null)
{
da.Fill(ds, tableName);
}
else
{
da.Fill(ds);
}
return ds;
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// 通过存储过程来查询班级或者全校成绩
/// </summary>
/// <param name="tableName">表名</param>
/// <returns></returns>
public DataSet GetScoreList(string tableName = null)
{
//视图可以看成一张表,直接像sql语句一样用,直接查询
string cmdText = "select * from view_GetScoreList";
return SQLHelper.GetTableData(cmdText,false,tableName);
}
3. 视图和普通的SQL语句查询比较
【1】视图本身就是一个提前写好的查询。但是这个查询保存到数据库服务器端。应用程序通过调用可以直接执行。
【2】普通的SQL语句查询。它在应用程序端。要执行,需要通过程序把SQL语句发送到数据库服务器端。
【3】后期的查询维护不同。如果我们要通过应用程序发送SQL语句,你必须要修改程序。但是如果我们使用视图呢?
可以适当的直接在数据库服务器上修改。
4. 视图本身的特点:本身不保存任何数据,只是保存到服务器端的一段编译好的SQL语句而已,并且已经优化好和编译好。
5. 关于使用建议:我们在学习阶段,必须会使用脚本写视图。如果是正式开发阶段,我们可以适当的使用可视化方式创建视图。
创建完毕后,把SQL语句优化好,再复制到你要创建的视图中。这个仅仅是为了省时间。必要的时候可以使用。
6. 视图还有一个非常重要的功能:比如我们在项目中会根据不同的角色,做不同的数据查询,这时候,我们在必要的时候完全可以
针对不同的用户角色,设计不同的视图,保证数据的安全。
二.存储过程
1. 概念:存储过程就是编写到数据库服务器端的SQL语句,存储过程的内容不仅仅是可以实现查询,也可以实现CRUD同时操作。
使用选择:如果仅仅是查询,建议你使用视图。尤其是针对不同的角色需要调用不同的视图。这时候视图是非常方便的。
2. 分类:系统存储过程(请大家自己学习一下,知道即可,可以随时查询)-->系统给我们提前定义好的,我们可以直接使用。
用户自定义存储过程(我们主要用的)
3. 好处:
【1】执行效率高。已经编译好,并保存到服务器端。只需要调用,必要的时候传递参数即可。
减轻客户端的压力。
【2】安全型好。客户端调用,只需要发送指令即可。数据安全有保障。
【3】维护方便。如果后续有改动,可以直接在服务器端修改即可,而客户端程序不用修改。
SQLSever存储过程
带输入参数的存储过程:
--存储过程编写
if exists(select * from sysobjects where name='Course__Procedure1')
drop procedure Course__Procedure1
go
--创建存储过程
create procedure Course__Procedure1
--定义传入参数
--@CourseId int,
@CourseName nvarchar(50),
@CourseContent nvarchar(500),
@ClassHour int,
@Credit int,
@CategoryId int,
@TeacherId int
as
---在这里编写具体的存储过程内容
insert into Course(CourseName,CourseContent,ClassHour,Credit,CategoryId,TeacherId)
values(@CourseName,@CourseContent,@ClassHour,@Credit,@CategoryId,@TeacherId);
go
--调用存储过程
exec Course__Procedure1 'opencv从入门到放弃','opencv从入门到高级教程',20,3,10,10
--查询
select * from Course where CourseName='opencv从入门到放弃' ;
带参数默认值的存储过程
-编写带参数默认值的存储过程
if exists(select * from sysobjects where name='Course__Procedure2')
drop procedure Course__Procedure2
go
create procedure Course__Procedure2
---添加存储过程参数
@courseName varchar(50)='opencv高级教程',
@courseContent varchar(500)='opencv高级教程,包你学会不放弃',
@ClassHour int,
@Credit int,
@CategoryId int,
@TeacherId int
as
---在这里添加具体的存储过程内容
insert into Course(CourseName,CourseContent,ClassHour,Credit,CategoryId,TeacherId)
values(@CourseName,@CourseContent,@ClassHour,@Credit,@CategoryId,@TeacherId);
go
--调用带默认参数值的存储过程,前两个参数使用默认值
exec Course__Procedure2 @ClassHour=10,@Credit=5,@CategoryId=12,@TeacherId=20
--调用带默认参数值的存储过程参数,第二个参数使用默认值
exec Course__Procedure2 @courseName='opencv图像处理教程',@ClassHour=10,@Credit=5,@CategoryId=12,@TeacherId=20
select * from Course where courseName='opencv图像处理教程'
带输出参数的存储过程,使用output修饰
--输出参数的存储过程:使用output
if exists(select * from sysobjects where name='Course__Procedure3')
drop procedure Course__Procedure3
go
create procedure Course__Procedure3
---定义输出参数
@Count int output
as
--编写具体存储过程内容
select @Count= Count(*) from Course;
go
--调用存储过程,声明变量用declare
declare @Count int --首先定义输出参数
exec Course__Procedure3 @Count output
--使用参数
select 商品总数=@Count
if exists(select * from sysobjects where name='select_usp_course1')
drop procedure select_usp_course1
go
create procedure select_usp_course1
--定义输入输出参数
@CountNum int output, ---定义输出参数
@CourseName nvarchar(50),
--@CourseContent nvarchar(500),
@CategoryId int
--@TeacherId int,
--@ClassHour int=1000,---带默认参数
--@Credit int=100---带默认值
as
select * from Course where Coursename=@CourseName;
select * from CourseCategory where CategoryId=@CategoryId;
select @CountNum=COUNT(*) from Course;
go
declare @CountNum int ;--声明输出变量
exec select_usp_course1 @CountNum output,'C#入门',12
在C#中调用写好的存储过程
#region 学员成绩管理 /// <summary>
/// 通过存储过程实现查询全校考试信息(通过存储过程)
/// </summary>
/// <returns>返回一个字典集合</returns>
public Dictionary<string, string> QueryExamInfo()
{
string cmdText = "pro_QueryExamInfo";
//定义输出参数,参数和数据库存储过程参数一致
SqlParameter outparam1 = new SqlParameter("@stuCount", SqlDbType.Int);
SqlParameter outparam2 = new SqlParameter("@agvCsharp", SqlDbType.Float);
SqlParameter outparam3 = new SqlParameter("@agvServerDB", SqlDbType.Float);
SqlParameter outparam4 = new SqlParameter("@absenceCount", SqlDbType.Int);
outparam1.Direction = ParameterDirection.Output;
outparam2.Direction = ParameterDirection.Output;
outparam3.Direction = ParameterDirection.Output;
outparam4.Direction = ParameterDirection.Output;
SqlParameter[] outparam = new SqlParameter[] {
outparam1,
outparam2,
outparam3,
outparam4
};
SqlDataReader reader = SQLHelper.GetReader(cmdText, outparam, true);
Dictionary<string, string> examInfoDic = null;
//获取参考学生人数,平均成绩
if (reader.Read())
{
examInfoDic = new Dictionary<string, string>()
{
["stuCount"] = reader["stuCount"].ToString(),
["agvCsharp"] = reader["agvCsharp"].ToString(),
["agvServerDB"] = reader["agvServerDB"].ToString(),
["absenceCount"] = reader["absenceCount"].ToString()
};
}
reader.Close();
return examInfoDic;
} public List<string> QueryAllAbsenceStudent()
{
string cmdText = "pro_QueryAllAbsenceStudent";
List<string> stuNameList = new List<string>();
SqlDataReader reader = SQLHelper.GetReader(cmdText);
while (reader.Read())
{
stuNameList.Add(reader["StudentName"].ToString());
}
reader.Close();
return stuNameList;
} /// <summary>
/// 按照班级查询考试信息
/// </summary>
/// <param name="ClassName"></param>
/// <returns></returns>
public Dictionary<string, string> QueryAbsenceInfoById(int ClassId)
{
string cmdText = "pro_QueryAbsenceInfoByClassId";
//定义输入参数
SqlParameter inputparam0 = new SqlParameter("@ClassId", ClassId);
//定义输出参数
SqlParameter outparam1 = new SqlParameter("@stuCount",SqlDbType.Int);
SqlParameter outparam2 = new SqlParameter("@agvCsharp",SqlDbType.Float);
SqlParameter outparam3 = new SqlParameter("@agvServerDB",SqlDbType.Float);
SqlParameter outparam4 = new SqlParameter("@absenceCount",SqlDbType.Int); inputparam0.Direction = ParameterDirection.Input;
outparam1.Direction = ParameterDirection.Output;
outparam2.Direction = ParameterDirection.Output;
outparam3.Direction = ParameterDirection.Output;
outparam4.Direction = ParameterDirection.Output;
SqlParameter[] param = new SqlParameter[] {
inputparam0,
outparam1,
outparam2,
outparam3,
outparam4
};
SqlDataReader reader = SQLHelper.GetReader(cmdText, param, true);
Dictionary<string, string> examInfoDic = null;
//获取参考学生人数,平均成绩
if (reader.Read())
{
examInfoDic = new Dictionary<string, string>()
{
["stuCount"] = reader["stuCount"].ToString(),
["agvCsharp"] = reader["agvCsharp"].ToString(),
["agvServerDB"] = reader["agvServerDB"].ToString(),
["absenceCount"] = reader["absenceCount"].ToString()
};
}
reader.Close();
return examInfoDic;
} /// <summary>
/// 按照班级查询缺考人员
/// </summary>
/// <param name="ClassName"></param>
/// <returns></returns>
public List<String> QueryAbsenceStudents(int ClassId)
{
string cmdText = "pro_QueryClassExamInfo";
SqlParameter[] param = new SqlParameter[] {
new SqlParameter("@ClassId",ClassId)
};
SqlDataReader reader = SQLHelper.GetReader(cmdText,param,true);
List<string> StuNamelist = new List<string>();
while (reader.Read())
{
StuNamelist.Add(reader["StudentName"].ToString());
}
reader.Close();
return StuNamelist;
}
#endregion
SQLSever视图和存储过程的更多相关文章
- Code First系列之视图,存储过程和异步API
返回<8天掌握EF的Code First开发>总目录 本篇目录 视图View 存储过程 使用存储过程CRUD 异步API 本章小结 自我测试 本系列的源码本人已托管于coding上:点击查 ...
- 8天掌握EF的Code First开发系列之5 视图、存储过程和异步API
本文出自8天掌握EF的Code First开发系列,经过自己的实践整理出来. 本篇目录 视图View 存储过程 异步API 本章小结 咱们接着上一篇继续深入学习,这一篇说说Entity Framewo ...
- 获取MSSQL Server中的相关信息(视图、存储过程、触发器、表)
在SQL SERVER得到某个数据库下面所有的表.视图.存储过程.触发器 select name from sysobjects where xtype='TR' --所有触发器select name ...
- sqlserver总结-视图及存储过程
视图中不能声明变量,不能调用存储过程,如果写比较复杂的查询,需要应用存储过程 视图也可以和函数结合 存储过程通过select或其他语句返回结果集 除此之外,存储过程返回结果只有两种方式 1 retur ...
- 查询数据库中表或视图或存储过程的数量 sql 语句
如果一个数据库中表的数量较多的话,那么在统计数据库中表的数量或视图或存储过程的数量时,如果还有一个一个去数,那就太麻烦了,其实可以通过 sql 语句来查询的,sql 语句的查询方法如下: sql se ...
- 在PowerDesigner中设计物理模型3——视图、存储过程和函数
原文:在PowerDesigner中设计物理模型3--视图.存储过程和函数 视图 在SQL Server中视图定义了一个SQL查询,一个查询中可以查询一个表也可以查询多个表,在PD中定义视图与在SQL ...
- mysql视图和存储过程定义者修改脚本(懒人专用)
前言: 在实际工作中mysql数据库的迁移.备份恢复.数据库重命名等一系列涉及到视图和存储过程定义者问题都会需要修改,每次都要从基础表获取数据,然后手工整理做脚本,十分麻烦,所以简单写了个过程,以后可 ...
- T-SQL应用,视图、存储过程、触发器、游标、临时表等
sqlserver常用操作: 视图.存储过程.触发器.函数 --*********************批处理********************* --[在一个批处理中存有一个语法错误,则所有 ...
- PowerDesigner建模应用(二)逆向工程,导出PDM文件前过滤元数据(表、视图、存储过程等)
在上一篇文章<PowerDesigner建模应用(一)逆向工程,配置数据源并导出PDM文件>步骤二中导出了目标数据库对应的PDM文件, 该文件中展示出了所有表的信息与关系. 某些业务场景下 ...
随机推荐
- 「题解报告」P7301 【[USACO21JAN] Spaced Out S】
原题传送门 神奇的5分算法:直接输出样例. 20分算法 直接把每个点是否有牛的状态DFS一遍同时判断是否合法,时间复杂度约为\(O(2^{n^2})\)(因为有判断合法的剪枝所以会比这个低).而在前四 ...
- PostgreSQL 大对象导出报错问题分析
1.前言 在处理用户问题过程遇到一个问题.用户通过pg_dump导出 bytea 对象时,当行的大小超过 1G时,会报错: [v8r6c5b41@dbhost01 ~]$ sys_dump -t t1 ...
- Linux_tail总结
tail 命令用法 功能从尾部显示文件若干行 语法: tail [ +/- num ][参数] 文件名 使用tail命令的-f选项可以方便的查阅正在改变的日志文件,tail -f filename会把 ...
- re.sub()用法
原文链接:https://blog.csdn.net/jackandsnow/article/details/103885422
- Windows Server体验之SSH远程连接
经过之前的各种远程管理方法,Windows Server可以被很好的管理,也能符合大多数Windows管理员的使用习惯.不过既然是命令行版本的Windows能不能和Linux一样管理呢?Windows ...
- Kubernetes(K8S)是什么?
概述 Kubernetes,又称为 k8s(首字母为 k.首字母与尾字母之间有 8 个字符.尾字母为 s,所以简称 k8s)或者简称为 "kube" ,是一种可自动实施 Linux ...
- [BJDCTF2020]Easy MD5 WP
老样子 打开看看 你会发现 啥也没有 有一个输入框,随便输入看看 抓包发现跳转leveldo4.php 同时看到 hint 里面有select * from 'admin' where passwor ...
- 4.第三篇 PKI基础概念、cfssl工具介绍及kubernetes中证书
文章转载自:https://mp.weixin.qq.com/s?__biz=MzI1MDgwNzQ1MQ==&mid=2247483787&idx=1&sn=08dd3404 ...
- 使用Elasticsearch中的copy_to来提高搜索效率
在今天的这个教程中,我们来着重讲解一下如何使用Elasticsearch中的copy来提高搜索的效率.比如在我们的搜索中,经常我们会遇到如下的文档: { "user" : &quo ...
- Beats:Beats 入门教程 (一)