一.视图(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. 牛客练习赛99—C

    数的和与积 https://ac.nowcoder.com/acm/contest/34330/C 思路: 2和4是不可以的,除了3意外其他的都可以用三项解决,其中一项为1,剩余两项分别设为x,y.  ...

  2. Elasticsearch7.6.2 RestHighLevelClient查询用法 must should(and or 关系)

    1. 引入jar <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId&g ...

  3. 使用kubectl管理Kubernetes(k8s)集群:常用命令,查看负载,命名空间namespace管理

    目录 一.系统环境 二.前言 三.kubectl 3.1 kubectl语法 3.2 kubectl格式化输出 四.kubectl常用命令 五.查看kubernetes集群node节点和pod负载 5 ...

  4. [Python]-sklearn.model_selection模块-处理数据集

    拆分数据集train&test from sklearn.model_selection import train_test_split 可以按比例拆分数据集,分为train和test x_t ...

  5. PHP 使用AES加密,并扩展失效时间检测

    /** * 具有时间校验的AES加密 * @param string $string 要处理的字符串 * @param int $timeout 超时时间,单位秒 * @param string $t ...

  6. day04-1群聊功能

    多用户即时通讯系统04 4.编码实现03 4.5功能实现-群聊功能实现 4.5.1思路分析 群聊的实现思路和私聊的实现非常类似. 不同的是:私聊时,服务端接收到消息后,只需要找出接收方的socket并 ...

  7. MinIO Python Client SDK 快速入门指南

    官方文档地址:http://docs.minio.org.cn/docs/master/python-client-quickstart-guide MinIO Python Client SDK提供 ...

  8. 6.使用nexus3配置yum私有仓库

    yum相较于rpm,能够更好地解决安装软件时的依赖包问题,使用yum安装更简单更方便.搭建本地YUM源服务器,可以避免升级安装软件时占用公网带宽:有了本地YUM源服务器,可以解决无法连接Interne ...

  9. css3_媒介查询

    !!!做媒介查询页面大小时,一定要加: <meta name="viewport" content="width=device-width, initial-sca ...

  10. 记Windows的一个存在了十多年的bug

    bug Windows有一个bug,持续了十多年,从Windows Visita开始(2007年),一直存在,直到Windows11(2021年)才修复(其实也不叫修复,后面我再具体说),而Windo ...