一.视图(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视图和存储过程的更多相关文章

  1. Code First系列之视图,存储过程和异步API

    返回<8天掌握EF的Code First开发>总目录 本篇目录 视图View 存储过程 使用存储过程CRUD 异步API 本章小结 自我测试 本系列的源码本人已托管于coding上:点击查 ...

  2. 8天掌握EF的Code First开发系列之5 视图、存储过程和异步API

    本文出自8天掌握EF的Code First开发系列,经过自己的实践整理出来. 本篇目录 视图View 存储过程 异步API 本章小结 咱们接着上一篇继续深入学习,这一篇说说Entity Framewo ...

  3. 获取MSSQL Server中的相关信息(视图、存储过程、触发器、表)

    在SQL SERVER得到某个数据库下面所有的表.视图.存储过程.触发器 select name from sysobjects where xtype='TR' --所有触发器select name ...

  4. sqlserver总结-视图及存储过程

    视图中不能声明变量,不能调用存储过程,如果写比较复杂的查询,需要应用存储过程 视图也可以和函数结合 存储过程通过select或其他语句返回结果集 除此之外,存储过程返回结果只有两种方式 1 retur ...

  5. 查询数据库中表或视图或存储过程的数量 sql 语句

    如果一个数据库中表的数量较多的话,那么在统计数据库中表的数量或视图或存储过程的数量时,如果还有一个一个去数,那就太麻烦了,其实可以通过 sql 语句来查询的,sql 语句的查询方法如下: sql se ...

  6. 在PowerDesigner中设计物理模型3——视图、存储过程和函数

    原文:在PowerDesigner中设计物理模型3--视图.存储过程和函数 视图 在SQL Server中视图定义了一个SQL查询,一个查询中可以查询一个表也可以查询多个表,在PD中定义视图与在SQL ...

  7. mysql视图和存储过程定义者修改脚本(懒人专用)

    前言: 在实际工作中mysql数据库的迁移.备份恢复.数据库重命名等一系列涉及到视图和存储过程定义者问题都会需要修改,每次都要从基础表获取数据,然后手工整理做脚本,十分麻烦,所以简单写了个过程,以后可 ...

  8. T-SQL应用,视图、存储过程、触发器、游标、临时表等

    sqlserver常用操作: 视图.存储过程.触发器.函数 --*********************批处理********************* --[在一个批处理中存有一个语法错误,则所有 ...

  9. PowerDesigner建模应用(二)逆向工程,导出PDM文件前过滤元数据(表、视图、存储过程等)

    在上一篇文章<PowerDesigner建模应用(一)逆向工程,配置数据源并导出PDM文件>步骤二中导出了目标数据库对应的PDM文件, 该文件中展示出了所有表的信息与关系. 某些业务场景下 ...

随机推荐

  1. APICloud AVM框架 封装车牌号输入键盘组件

    AVM(Application-View-Model)前端组件化开发模式基于标准Web Components组件化思想,提供包含虚拟DOM和Runtime的编程框架avm.js以及多端统一编译工具,完 ...

  2. windows优化原神

    原神3.0新地图很卡顿? 锐距显卡带不动? 看一下我的配置 英特尔i5-1135G7 内存16GB可以拓展32GB 固态512GB 原神优化前帧率50左右 优化后59-60最差55 展示图原神设置图 ...

  3. django_day04

    django_day04 路由 from django.conf.urls import url urlpatterns = [ url(正则表达式, views视图,参数,别名), ] 正则表达式 ...

  4. js 数组中的方法

    <!DOCTYPE html><html><head> <title>数组的方法</title> <meta charset=&quo ...

  5. 万星开源项目强势回归「GitHub 热点速览 v.22.38」

    本周霸榜的 GitHub 项目多为老项目,比如:老面孔的 theatre 凭借极其优秀的动画功底连续三天霸榜 TypeScript 类目.借 Figma 被 Adobe 收购之风,又出现在 GitHu ...

  6. 并发原理 — CPU原子性指令(一)

    本篇文章将以Intel CPU作为讨论基础 一.并发的由来 一台计算机有2个cpu,其中CPU1执行程序A,CPU2执行程序B,由于程序A和程序B是两个不同的应用程序,所以它们两个之间并不存在并发问题 ...

  7. .NET 部署Https(SSL)通过代码方式

    在上一个文章中,传送门,给大家介绍了怎么在配置文件中使用 Kestrel 部署 Https,正好今天有小伙伴稳问到:可以通过代码的方式实现 Kestrel 的 Https 的部署吗?答案是肯定的,我们 ...

  8. Kubernetes 监控--Alertmanager

    前面我们学习 Prometheus 的时候了解到 Prometheus 包含一个报警模块,就是我们的 AlertManager,Alertmanager 主要用于接收 Prometheus 发送的告警 ...

  9. Pod原理

    Pod 是 Kubernetes 集群中最基本的调度单元,我们平时在集群中部署的应用都是以 Pod 为单位的,而并不是我们熟知的容器,这样设计的目的是什么呢?为何不直接使用容器呢? 为什么需要 Pod ...

  10. Mapping

    dynamic针对的是新增的字段,不是对mapping中已有的字段 (原有mapping中的字段不受影响,只影响新增的字段) 当dynamic被设置成false的时候,存在新增字段可以被写入到索引文件 ...