C#高级:在SQLserver中使用视图、存储过程、索引和触发器

news2024/9/22 1:29:08

目录

一、视图

1.视图是什么,有什么作用?

2.视图和存储过程有什么区别?

3.建立一个视图,名为PersonBorrowView,SQL已给出:

4.如果往BorrowInfo加一条记录,我原本的SQL会增加一条记录,那么查询视图,数据会增加吗?

5.写出查询视图的SQL。

6.写出根据视图名获取视图的SQL

7.小结:

二、存储过程

1.创建一个存储过程(一键归还非管理员用户2024年借的书),要求做以下几件事情:

2.写出执行存储过程的SQL/方法

3.假设一个存储过程分为4步,第2步发现报错,那么它会执行1、2步,还是都不执行呢?

4.谈谈临时表和公共表达式的区别

5.存储过程的出入参和异常处理

三、索引

1.索引是什么,创建索引有什么好处

2.以下SQL装载10万数据,每天被查询1000多万次,建议怎么设置索引?

3.写出创建索引的SQL(单个索引和复合索引各列举一条)

4.写出根据表名获取索引设置情况的方法

 5.为什么主键一般不设置为索引?

四、触发器

1.触发器是什么,使用有什么好处

2.触发器有多少种类型

3.请你完成三个触发器SQL的编写:

4.查询触发器

5.触发器可以接收外部入参吗,为什么?

五、事务

1.事务是什么,运用事务有什么好处?

2.事务的重要操作有哪些?

3.演示一个事务SQL

4.事务隔离性有哪些,特点是啥?


一、视图

1.视图是什么,有什么作用?

①一个虚拟表

②简化查询

2.视图和存储过程有什么区别?

①视图:用于简化查询和数据展示

②存储过程:用于执行一系列SQL语句,包含增删改查等,即业务逻辑得处理。

3.建立一个视图,名为PersonBorrowView,SQL已给出:

  SELECT U.Name,BW.BoTime,BI.BookName FROM UserInfo U
  INNER JOIN BorrowInfo BW ON U.UserID=BW.UserID
  INNER JOIN BookInfo BI ON BW.BookID=BI.BookID

【解答】建立视图的SQL语句:

CREATE VIEW PersonBorrowView AS
SELECT U.Name, BW.BoTime, BI.BookName
FROM UserInfo U
INNER JOIN BorrowInfo BW ON U.UserID = BW.UserID
INNER JOIN BookInfo BI ON BW.BookID = BI.BookID;

4.如果往BorrowInfo加一条记录,我原本的SQL会增加一条记录,那么查询视图,数据会增加吗?

会,因为查询视图,本质是查询视图保存的SQL

5.写出查询视图的SQL。

SELECT * FROM PersonBorrowView;

6.写出根据视图名获取视图的SQL

SELECT OBJECT_DEFINITION(OBJECT_ID('PersonBorrowView')) AS VIEWSQL;

7.小结:

-- 建立视图:
CREATE VIEW 视图名 AS
SQL-- 写你的查询SQL

-- 查询视图:
SELECT * FROM 视图名

-- 根据视图名查询视图保存的SQL:
SELECT OBJECT_DEFINITION(OBJECT_ID('视图名')) AS VIEWSQL

二、存储过程

1.创建一个存储过程(一键归还非管理员用户2024年借的书),要求做以下几件事情:

-- 筛选出需要一键归还的用户
SELECT UserID,Name FROM UserInfo WHERE Power !=1

-- 筛选出2024年未归还的书
SELECT BorID,UserID,BookID FROM BorrowInfo Where Year(BoTime)='2024' and BackTime is null and UserID in (xxxxx)

-- 将这些书的归还状态更新为今天
Update BorrowInfo set BackTime = GETDATE() Where  BorID in (xxxxx)

-- 将一键归还涉及到的用户、书名、还款日期插入到PC_Table中
INSERT INTO PC_TABLE  ([PCName],[PCBoTime],[PCBookName]) VALUES(xxxx)

【解答:存储过程的创建SQL】

  定义存储过程的名称:ReturnBooksForNonAdmin2024

  另外定义一些临时表去推进存储过程的流程

CREATE PROCEDURE ReturnBooksForNonAdmin2024
AS
BEGIN
    -- 1. 筛选出需要一键归还的用户
    DECLARE @NonAdminUsers TABLE (UserID NVARCHAR(100), Name NVARCHAR(100));
    INSERT INTO @NonAdminUsers (UserID, Name)
    SELECT UserID, Name
    FROM UserInfo
    WHERE Power != 1;

    -- 2. 筛选出2024年未归还的书
    DECLARE @BooksToReturn TABLE (BorID NVARCHAR(100), UserID NVARCHAR(100),BookID NVARCHAR(100));
    INSERT INTO @BooksToReturn (BorID, UserID,BookID)
    SELECT BorID, UserID,BookID
    FROM BorrowInfo
    WHERE YEAR(BoTime) = 2024
    AND BackTime IS NULL
    AND UserID IN (SELECT UserID FROM @NonAdminUsers);

    -- 3. 将这些书的归还状态更新为今天
    UPDATE BorrowInfo
    SET BackTime = GETDATE()
    WHERE BorID IN (SELECT BorID FROM @BooksToReturn);

    -- 4. 将一键归还涉及到的用户、书名、还款日期插入到PC_TABLE中
    INSERT INTO PC_TABLE ([PCName], [PCBoTime], [PCBookName])
    SELECT u.Name AS [PCName], GETDATE() AS [PCBoTime], bi.BookName AS [PCBookName]
    FROM @BooksToReturn b
    JOIN UserInfo u ON b.UserID = u.UserID
    JOIN BookInfo bi ON b.BookID= bi.BookID;

END;

2.写出执行存储过程的SQL/方法

EXECUTE ReturnBooksForNonAdmin2024;

【查询某个存储过程的SQL】


3.假设一个存储过程分为4步,第2步发现报错,那么它会执行1、2步,还是都不执行呢?

取决于SQL的事务

  • 如果步骤1和步骤2在同一个事务中执行,并且第2步失败,步骤1也不会生效。
  • 如果每一步都在独立的事务中,那么步骤1和步骤2会分别执行,失败的步骤不会影响之前成功的步骤。

(本例的存储过程没有指定事务,因此会被当做是独立的事务,因此会执行第1、2步,而不执行后续的SQL)

4.谈谈临时表和公共表达式的区别

-- 临时表
DECLARE @NonAdminUsers TABLE (UserID NVARCHAR(100), Name NVARCHAR(100));
INSERT INTO @NonAdminUsers (UserID, Name)
SELECT UserID, Name
FROM UserInfo
WHERE Power != 1;
SELECT * FROM @NonAdminUsers

-- 公共表达式CTE
WITH NonAdminUsers AS
(
    SELECT UserID, Name
    FROM UserInfo
    WHERE Power != 1
)
SELECT * FROM NonAdminUsers

【区别和特点】

  1. 作用域: 临时表通常用于存储过程或复杂逻辑,公共表达式(CTE)更适合单次查询,特别是递归查询。
  2. 复杂性: 临时表处理复杂的增删改查操作时更具优势。
  3. 用途: 公共表达式适合在查询中引用和计算临时数据。

5.存储过程的出入参和异常处理

【需求】

        传入一个USERID,如果查到下面的SQL则插入,查不到就不插入,且查到且成功插入返回1,查不到返回0,查到了插入失败返回-99

SELECT U.Name,BW.BoTime,BI.BookName FROM UserInfo U
INNER JOIN BorrowInfo BW ON U.UserID=BW.UserID
INNER JOIN BookInfo BI ON BW.BookID=BI.BookID
WHERE U.UserID=''

【创建存储过程】

CREATE PROCEDURE InsertUserData
    @UserID NVARCHAR(100),  -- 输入的用户ID
    @Result INT OUTPUT     -- 输出结果
AS
BEGIN
    -- 初始化结果为0
    SET @Result = 0;

    -- 使用事务处理数据插入操作
    BEGIN TRANSACTION;

    BEGIN TRY
        -- 检查是否有记录需要插入
        IF EXISTS (
            SELECT 1
            FROM UserInfo U
            INNER JOIN BorrowInfo BW ON U.UserID = BW.UserID
            INNER JOIN BookInfo BI ON BW.BookID = BI.BookID
            WHERE U.UserID = @UserID
        )
        BEGIN
            -- 将所有相关数据插入目标表
            INSERT INTO PC_TABLE ([PCName], [PCBoTime], [PCBookName])
            SELECT U.Name, BW.BoTime, BI.BookName
            FROM UserInfo U
            INNER JOIN BorrowInfo BW ON U.UserID = BW.UserID
            INNER JOIN BookInfo BI ON BW.BookID = BI.BookID
            WHERE U.UserID = @UserID;

            -- 如果插入成功,设置结果为1
            SET @Result = 1;
        END
        ELSE
        BEGIN
            -- 如果没有记录符合条件,设置结果为0
            SET @Result = 0;
        END

        -- 提交事务
        COMMIT TRANSACTION;
    END TRY
    BEGIN CATCH
        -- 如果发生错误,回滚事务
        ROLLBACK TRANSACTION;

        -- 设置结果为-99
        SET @Result = -99;
    END CATCH
END

【执行存储过程】

DECLARE @OutputResult INT;

EXEC InsertUserData @UserID = 'some_user_id', @Result = @OutputResult OUTPUT;

-- 查询输出结果
SELECT @OutputResult AS Result;

三、索引

1.索引是什么,创建索引有什么好处

①提高数据库查询效率的数据结构。
②可以让数据库系统快速查找到特定的数据行。

2.以下SQL装载10万数据,每天被查询1000多万次,建议怎么设置索引?

SELECT * FROM [BookManage].[dbo].[BookInfo] WHERE Author = 'XXX'

如果 Author 是主要的查询条件列,则应对 Author 列创建索引。

3.写出创建索引的SQL(单个索引和复合索引各列举一条)

CREATE INDEX IX_Author ON BookManage.dbo.BookInfo (Author);

CREATE INDEX IX_BookName_Author ON BookManage.dbo.BookInfo (BookName, Author);

4.写出根据表名获取索引设置情况的方法

【方法一:SSMS查找】

【方法二:SQL查找】

-- 获取指定表的索引信息
SELECT 
    t.name AS TableName,
    i.name AS IndexName,
    i.type_desc AS IndexType,
    c.name AS ColumnName,
    ic.index_column_id AS ColumnID,
    ic.key_ordinal AS KeyOrdinal
FROM 
    sys.indexes AS i
    INNER JOIN sys.index_columns AS ic
        ON i.object_id = ic.object_id AND i.index_id = ic.index_id
    INNER JOIN sys.columns AS c
        ON ic.object_id = c.object_id AND ic.column_id = c.column_id
    INNER JOIN sys.tables AS t
        ON i.object_id = t.object_id
WHERE 
    t.name = 'BookInfo'  -- 指定表名
ORDER BY 
    i.name, ic.index_column_id;

说明:

 5.为什么主键一般不设置为索引?

因为创建主键时会自动创建一个聚集索引,以确保数据的唯一性和高效的查找。

四、触发器

1.触发器是什么,使用有什么好处

①定义:附加到表或视图上的一个特殊类型的存储过程。
②好处:在某表(视图)发生增删改时自动化地执行定义好的SQL。(可选是增删改某表前执行,还是增删改某表后执行

2.触发器有多少种类型

①按状态分:
INSERT 触发器: 在插入操作之前或之后执行。
UPDATE 触发器: 在更新操作之前或之后执行。
DELETE 触发器: 在删除操作之前或之后执行。
INSTEAD OF 触发器: 替代执行触发器所附加的操作,这意味着触发器内的操作会取代原来的操作。

②按时间分:
BEFORE触发器:在数据操作语句(如INSERT、UPDATE、DELETE)执行之前触发。
AFTER触发器:在数据操作语句执行之后触发。

3.请你完成三个触发器SQL的编写:

  • LogInfo表:ID,LogTime,Remarks
  • UserInfo表作更新(Update)前,将信息插入到LogInfo表中(ID:NEWID())
  • UserInfo表作新增(Insert)后,将信息插入到LogInfo表中(ID:NEWID())
  • BorrowInfo表作删除(Delete)后,将信息插入到LogInfo表中(ID:NEWID())
-- UserInfo表作更新(Update)前,将信息插入到LogInfo表中(ID:NEWID())
CREATE TRIGGER trg_UserInfo_Update_Before
ON dbo.UserInfo
AFTER UPDATE
AS
BEGIN
    INSERT INTO dbo.LogInfo (ID, LogTime, Remarks)
    SELECT 
        NEWID() AS ID,
        GETDATE() AS LogTime,
        'Update Operation: ID = ' + CAST(i.UserID AS VARCHAR(50)) + ', Updated By = ' + SYSTEM_USER AS Remarks
    FROM 
        inserted i  -- 这里的i指的是UserInfo表,下同
END;


-- UserInfo表作新增(Insert)后,将信息插入到LogInfo表中(ID:NEWID())
CREATE TRIGGER trg_UserInfo_Insert_After
ON dbo.UserInfo
AFTER INSERT
AS
BEGIN
    INSERT INTO dbo.LogInfo (ID, LogTime, Remarks)
    SELECT 
        NEWID() AS ID,
        GETDATE() AS LogTime,
        'Insert Operation: ID = ' + CAST(i.UserID AS VARCHAR(50)) + ', Inserted By = ' + SYSTEM_USER AS Remarks
    FROM 
        inserted i
    -- 这里也可以使用 WHERE 子句来筛选特定的记录
END;


-- BorrowInfo表作删除(Delete)后,将信息插入到LogInfo表中(ID:NEWID())
CREATE TRIGGER trg_BorrowInfo_Delete_After
ON dbo.BorrowInfo
AFTER DELETE
AS
BEGIN
    INSERT INTO dbo.LogInfo (ID, LogTime, Remarks)
    SELECT 
        NEWID() AS ID,
        GETDATE() AS LogTime,
        'Delete Operation: ID = ' + CAST(d.UserID AS VARCHAR(50)) + ', Deleted By = ' + SYSTEM_USER AS Remarks
    FROM 
        deleted d
    -- 这里也可以使用 WHERE 子句来筛选特定的记录
END;

4.查询触发器

【方法一:SSMS】

【方法二:SQL】

SELECT 
    t.name AS TriggerName,
    o.name AS TableName
FROM 
    sys.triggers t
INNER JOIN 
    sys.objects o
    ON t.parent_id = o.object_id
WHERE 
    o.name = 'UserInfo'; -- 替换为你的表名

5.触发器可以接收外部入参吗,为什么?

①不可以
②防止注入风险;简化设计,确保其可维护性;

五、事务

1.事务是什么,运用事务有什么好处?

①定义:事务是一个或者多个SQL,一个事务要么全部成功,要么全部失败。(ACID属性)
②好处:事务执行过程中发生错误或故障,事务可以被回滚到其开始前的状态,防止数据损坏。

2.事务的重要操作有哪些?

BEGIN TRANSACTION:开始一个新的事务。
COMMIT:提交事务,保存事务中的所有操作,使它们对其他事务可见。提交操作将所有更改写入数据库。
ROLLBACK:回滚事务,撤销事务中的所有操作,将数据库恢复到事务开始前的状态。

3.演示一个事务SQL

-- 开始事务
BEGIN TRANSACTION;

-- 执行多个数据库操作
INSERT INTO [dbo].[LogInfo]
           ([ID]
           ,[LogTime]
           ,[Remarks])
     VALUES
           (NEWID()
           ,GETDATE()
           ,'执行了插入操作')

-- 提交事务
--COMMIT;

-- 回滚事务
--ROLLBACK;

SELECT * FROM LogInfo

问题:
①如果开始事务后,执行SQL,然后既不执行提交事务,又不执行回滚事务,会怎么样?

对数据的修改都会在事务结束之前保持在事务的上下文中。

事务通常会在数据库连接关闭时自动回滚,或者在数据库服务器重启时也会回滚未提交的事务。

②开始事务后,执行SQL,还没提交,为何就可以查出数据了?

SQLsever默认自动提交事务,且隔离级别默认设置是"读已提交"隔离级别,事务内的查询会看到其他事务已提交的更改。

4.事务隔离性有哪些,特点是啥?

  • 读未提交(Read Uncommitted):可读到:开启事务+SQL增删改(未提交)的数据
  • 读已提交(Read Committed):默认,可读到:开启事务+SQL增删改后提交的数据(不开启事务默认执行SQL自动提交)
  • 可重复读(Repeatable Read):开启事务1读A表,此时A表插入新数据,再读A表,读不到新数据,直到事务1提交后读A表才看得到。
  • ‌串行化(Serializable):开启事务1读A表,此时A表插入新数据,发现插入失败,直到事务1提交后,才可以插入新数据(事务隔离,需排队)。


 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2034623.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JAVA毕业设计635—基于Java+ssm的仓库管理系统(源代码+数据库)

毕设所有选题: https://blog.csdn.net/2303_76227485/article/details/131104075 基于Javassm的仓库管理系统(源代码数据库)635 一、系统介绍 分为员工、管理员两种角色 1、员工: 登录、库存管理、出入库管理、密码修改 2、管理员: 库…

(自用)交互协议设计——protobuf序列化

protobuf是一种比json和xml等序列化工具更加轻量和高效的结构化数据存储格式,性能比json和xml真的强很多,毕竟google出品。 protobuf原理 protobuf如何使用 创建xxx.proto文件 开头写上 syntax"proto2"package tutorial; 表明使用的proto…

Linux:修改网卡名称(redhat-centos-redora)

解决问题: 我现在有块网卡名ens160,我想把他改为ens33(仅是模拟,实际中你可以任意更改,不是局限在这两名称中,举一反三) 我当前的操作系统为:centos9 解决办法: 1.修改grub配置 …

前端学习笔记-JS篇-02

运算符 赋值运算符 对变量进行赋值的运算符。 已经学过的赋值运算符:【将等号右边的值赋予给左边,要求左边必须是一个容器】 其他赋值运算符: - * / % 原始写法和简化写法【其实就是java基础】 一元运算符 众多的JavaScript 的运…

免费【2024】springboot 个人健康管理网站的设计与实现

博主介绍:✌CSDN新星计划导师、Java领域优质创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流✌ 技术范围:SpringBoot、Vue、SSM、HTML、Jsp、PHP、Nodejs、Python、爬虫、数据可视化…

php 企业员工考勤系统—计算机毕业设计源码17108

摘要 由于数据库和数据仓库技术的快速发展,企业员工考勤系统建设越来越向模块化、智能化、自我服务和管理科学化的方向发展。员工管理系统对处理对象和服务对象,自身的系统结构,处理能力,都将适应技术发展的要求发生重大的变化。 …

Linux系统安全及应用(二):PAM安全认证

文章目录 4Linux中的PAM安全认证介绍su命令的安全隐患PAM认证原理和构成PAM安全认证流程PAM 配置文件结构说明PAM 控制标记的补充说明PAM 实例 4Linux中的PAM安全认证 介绍 PAM(Pluggable Authentication Modules),可插拔式认证模块是一种高…

高翔【自动驾驶与机器人中的SLAM技术】学习笔记(七)卡尔曼滤波器三:卡尔曼滤波器公式推导【转载】

卡尔曼滤波器三:卡尔曼公式推导 转载来源:卡尔曼滤波:从入门到精通 简述 考虑一个SLAM 问题,它由一个运动方程: x t f ( x t − 1 , u t ) ω t (1) \mathbf{x}_{t}f(\mathbf{x}_{t-1},\mathbf{u}_{t}) \omega_…

尚品汇-ES(三十一)

目录: (1)封装搜索相关实体对象 (2)搜索接口封装 (3)在service-list-client模块添加远程接口 (1)封装搜索相关实体对象 搜索参数实体:SearchParam 搜索参…

haproxy高级功能配置

介绍HAProxy高级配置及实用案例 一.基于cookie会话保持 cookie value:为当前server指定cookie值,实现基于cookie的会话黏性,相对于基于 source 地址hash 调度算法对客户端的粒度更精准,但同时也加大了haproxy负载,目前此模式使用…

Service服务在Android中的使用

目录 一,Service简介 二,Service的两种启动方式 1,非绑定式启动Service 2,绑定式启动Service 三,Service的生命周期 1,非绑定式Service的生命周期 2,绑定式Service的生命周期 四&#xf…

BCArchive加密工具实测分享:为何我觉得它很实用?

前言 你是不是经常有这样的烦恼:重要的文件、私密的照片、敏感的资料,总是担心会不小心泄露出去?哎呀,别担心,别担心,我今天要介绍的这款软件,简直就是守护你数据安全的超级英雄! 在…

CVE-2012-2122 mysql/mariaDB身份认证漏洞

简介: 当连接MariaDB/MySQL时,输入的密码会与期望的正确密码比较,不断的尝试登录连接,回导致MySQL认为两个密码是相同的。也就是说只要知道用户名,不断尝试就能够直接登入SQL数据库。 影响范围#所有的Mariadb和mysql版…

【吊打面试官系列-Elasticsearch面试题】Elasticsearch 在部署时,对 Linux 的设置有哪些优化方法?

大家好,我是锋哥。今天分享关于 【Elasticsearch 在部署时,对 Linux 的设置有哪些优化方法?】面试题,希望对大家有帮助; Elasticsearch 在部署时,对 Linux 的设置有哪些优化方法? 1、64 GB 内存…

【STM32】CubeMX + CLion + FreeRTOS移植过程问题记录

文章目录 一、portable 文件选择二、自定义文件添加三、ST-Link v2 烧录问题四、STM32F407工程中程序无法启动调度器 前言   本文依照稚晖君分享的配置CLion用于STM32开发【优雅の嵌入式开发】,尝试配置STM32CubeMX CLion开发环境,并在此基础上移植Fre…

利用Emgucv绘制条形码边框16(C#)

EmguCV环境配置: ​​​​​​Emgu CV4图像处理之环境搭建1(C#)_emgucv 4.7-CSDN博客 本文测试环境: win10 64位 vistual studio 2019 Emgu CV 4.6.0 环境配置准备: 1 新增控制台项目,.net framework为4.7.2 2 把win-x…

minikube 实践练习

前言 我这里就简单跟着官方教程做了下练习 参考文档:https://v1-27.docs.kubernetes.io/zh-cn/docs/tutorials/hello-minikube/ 这里最重要的是,你需要提前配置好你的网络。 这个我教不了,之前发了篇帖子vmware实现科学上网审核不通过&…

ElasticSearch 全文检索相关性 算分

文章目录 相关性相关性Relevance相关性算法TF-IDFBM25 通过Explain查看TF-IDFboosting query 多字段查询 相关性dis_max query最佳字段查询multi_match querybest_fields最佳匹配字段most_fields 多数字段搜索cross_fields跨字段搜索 相关性 相关性Relevance 搜索的相关性算分…

Ubuntu 通过 docker 安装 Nginx 镜像 + 创建并运行 nginx01 容器

一、安装 nginx:精简版镜像 1. 查找有什么类型的 nginx 镜像 yammiemy-pc >/home/yammie $ docker search nginx 2. 下载精简版 nginx 镜像 yammiemy-pc >/opt $ docker pull nginx:alpine alpine: Pulling from library/nginx 46b060cc2620: Already exists 21af147…

【深度学习|目标跟踪】快速入门卡尔曼滤波!

卡尔曼滤波详解 申明一、什么是卡尔曼滤波1.1 卡尔曼滤波的使用场景1.2 卡尔曼滤波的定义 二、卡尔曼滤波公式详解(无推导)三、卡尔曼滤波的简单应用 申明 本博客参考了b站up主“华南小虎队”的卡尔曼滤波教学视频以及Lauszus Kristian Sloth Lauszus的卡…