首页 > 数据库 >sql server 练习:存储过程+临时表+游标

sql server 练习:存储过程+临时表+游标

时间:2023-07-15 16:12:19浏览次数:31  
标签:00 Name Dep 游标 server fMoney fUser sql Test

1、题目

要求编写一个存储过程 spGetTest 统计 T_Test 表的数据,执行输出结果如下图:

2、数据

if not object_id('T_Test') is null  --判断表是否存在
   drop table T_Test  --删除表
go 
--创建用户金额发生表 
create table T_Test(
   fUser_Name nvarchar(40), --用户名称 
   fUser_Dep  nvarchar(40), --用户部门
   fMoney     numeric(24,6), --用户发生金额
   fDate      datetime       --金额发生时间
)


go 
--插入测试数据
insert T_Test(fUser_Name,fUser_Dep,fMoney,fDate)
values('小王','营业部',120.3,'2023/06/21 11:00:00')
insert T_Test(fUser_Name,fUser_Dep,fMoney,fDate)
values('小王','营业部',450,'2023/06/21 12:00:00')
insert T_Test(fUser_Name,fUser_Dep,fMoney,fDate)
values('小王','营业部',100,'2023/06/21 14:00:00')
insert T_Test(fUser_Name,fUser_Dep,fMoney,fDate)
values('小李','营业部',110.34,'2023/06/21 10:00:00')
insert T_Test(fUser_Name,fUser_Dep,fMoney,fDate)
values('小李','营业部',120,'2023/06/21 11:00:00')
go
insert T_Test(fUser_Name,fUser_Dep,fMoney,fDate)
values('老刘','生产部',300,'2023/06/21 19:00:00')
insert T_Test(fUser_Name,fUser_Dep,fMoney,fDate)
values('老刘','生产部',150,'2023/06/21 14:00:00')
insert T_Test(fUser_Name,fUser_Dep,fMoney,fDate)
values('郭总','生产部',220,'2023/06/21 11:00:00')
insert T_Test(fUser_Name,fUser_Dep,fMoney,fDate)
values('郭总','生产部',340,'2023/06/21 18:00:00')
insert T_Test(fUser_Name,fUser_Dep,fMoney,fDate)
values('郭总','生产部',60,'2023/06/21 16:00:00')
insert T_Test(fUser_Name,fUser_Dep,fMoney,fDate)
values('郭总','生产部',508,'2023/06/21 13:00:00')
go
insert T_Test(fUser_Name,fUser_Dep,fMoney,fDate)
values('孙总','储运部',400.06,'2023/06/21 14:00:00')
insert T_Test(fUser_Name,fUser_Dep,fMoney,fDate)
values('孙总','储运部',220,'2023/06/21 13:00:00')
insert T_Test(fUser_Name,fUser_Dep,fMoney,fDate)
values('孙总','储运部',520,'2023/06/21 15:00:00')
insert T_Test(fUser_Name,fUser_Dep,fMoney,fDate)
values('小黄','储运部',720,'2023/06/21 16:00:00')
insert T_Test(fUser_Name,fUser_Dep,fMoney,fDate)
values('小黄','储运部',150,'2023/06/21 18:00:00')
insert T_Test(fUser_Name,fUser_Dep,fMoney,fDate)
values('大彭','储运部',190.2,'2023/06/21 12:00:00')
insert T_Test(fUser_Name,fUser_Dep,fMoney,fDate)
values('大彭','储运部',170,'2023/06/21 16:00:00')
insert T_Test(fUser_Name,fUser_Dep,fMoney,fDate)
values('大彭','储运部',180,'2023/06/21 18:00:00')
insert T_Test(fUser_Name,fUser_Dep,fMoney,fDate)
values('大彭','储运部',409,'2023/06/21 12:00:00')
insert T_Test(fUser_Name,fUser_Dep,fMoney,fDate)
values('二胖','储运部',360,'2023/06/21 17:00:00')

3、实现

IF EXISTS (SELECT * FROM sys.objects WHERE name='proc_ybTest')
    DROP PROCEDURE proc_ybTest
GO

CREATE PROCEDURE proc_ybTest
AS
BEGIN
    DECLARE @depname NVARCHAR(20);
    DECLARE @results TABLE (部门 NVARCHAR(20), fUser_Name NVARCHAR(50), 金额 DECIMAL(18, 2), 最近消费时间 DATETIME);

    DECLARE dep_name CURSOR FOR SELECT fUser_Dep FROM T_Test GROUP BY fUser_Dep;
    OPEN dep_name;

    FETCH NEXT FROM dep_name INTO @depname;
    WHILE @@FETCH_STATUS = 0
    BEGIN
        INSERT INTO @results 
            SELECT
                CASE WHEN fUser_Dep=@depname THEN '' END AS 部门, 
                fUser_Name, SUM(fMoney) AS 金额, MAX(fDate) AS 最近消费时间
            FROM T_Test
            WHERE fUser_Dep = @depname
            GROUP BY fUser_Dep, fUser_Name
            UNION ALL
            SELECT @depname+'_合计', '', SUM(fMoney), null
            FROM T_Test
            WHERE fUser_Dep = @depname;

        FETCH NEXT FROM dep_name INTO @depname;
    END;

    CLOSE dep_name;
    DEALLOCATE dep_name;

    SELECT CASE 
        WHEN 部门 NOT LIKE '%合计%' THEN ''
        ELSE 部门
        END AS 部门,
    fUser_Name,金额,最近消费时间 FROM @results;
END

exec proc_ybTest

执行存储过程结果如下:

4、解释

4.1AI文字解释

以下是对存储过程进行逐行解释:

  1. IF EXISTS (SELECT * FROM sys.objects WHERE name='proc_ybTest'): 这行代码用于检查是否存在名为 proc_ybTest 的存储过程。

  2. DROP PROCEDURE proc_ybTest: 如果存在名为 proc_ybTest 的存储过程,则使用 DROP PROCEDURE 语句将其删除。

  3. GO: GO 是一个批处理分隔符,它将上述两行代码分隔为两个独立的批处理。

  4. CREATE PROCEDURE proc_ybTest: 创建名为 proc_ybTest 的存储过程。

  5. AS: AS 关键字指示存储过程的主体开始。

  6. DECLARE @depname NVARCHAR(20);: 声明一个名为 @depname 的变量,用于存储部门名称。

  7. DECLARE @results TABLE (部门 NVARCHAR(20), fUser_Name NVARCHAR(50), 金额 DECIMAL(18, 2), 最近消费时间 DATETIME);: 声明一个名为 @results 的表变量,用于存储结果集。

  8. DECLARE dep_name CURSOR FOR SELECT fUser_Dep FROM T_Test GROUP BY fUser_Dep;: 声明名为 dep_name 的游标,用于循环遍历部门名称。

  9. OPEN dep_name;: 打开游标,准备开始遍历。

  10. FETCH NEXT FROM dep_name INTO @depname;: 从游标中获取第一条部门名称,并将其存储在 @depname 变量中。

  11. WHILE @@FETCH_STATUS = 0: 进入一个循环,只要游标还有更多的数据可获取,就继续循环。

  12. BEGIN: 循环体的开始。

  13. INSERT INTO @results: 将以下查询结果插入到 @results 表变量中。

    • 部门行:根据当前部门名称(@depname)查询相应的部门数据,包括部门、用户名、金额和最近消费时间。
    • 合计行:根据当前部门名称(@depname)查询相应的金额合计,并将部门名称拼接上 "_合计" 后作为部门。
  14. FETCH NEXT FROM dep_name INTO @depname;: 从游标中获取下一条部门名称,并将其存储在 @depname 变量中。

  15. END: 循环体的结束。

  16. CLOSE dep_name;: 关闭游标。

  17. DEALLOCATE dep_name;: 释放游标的资源。

  18. SELECT CASE WHEN 部门 NOT LIKE '%合计%' THEN '' ELSE 部门 END AS 部门, fUser_Name, 金额, 最近消费时间 FROM @results;: 从 @results 表变量中选择部门、用户名、金额和最近消费时间,并使用 CASE 语句处理部门名称,使合计行的部门名称为空字符串。

 

标签:00,Name,Dep,游标,server,fMoney,fUser,sql,Test
From: https://www.cnblogs.com/Yytan-BK/p/17556288.html

相关文章

  • PostgreSQL 分组汇总(二)
    PostgreSQL除了支持基本的GROUPBY分组操作之外,还支持3种高级的分组选项:GROUPINGSETS、ROLLUP以及CUBE。GROUPINGSETS选项GROUPINGSETS是GROUPBY的扩展选项,用于指定自定义的分组集。举例来说,以下是一个销售数据表:CREATETABLEsales(itemVARCHAR(10),year......
  • mysql删除数据空间不释放
    MySQL删除数据空间不释放的原因及解决方法MySQL是一种广泛使用的关系型数据库管理系统,但在使用过程中可能会遇到一个问题:删除数据后,磁盘空间并没有被立即释放。这可能导致磁盘空间的浪费和性能下降。本文将解释这个问题的原因,并提供一些解决方法。问题原因MySQL中的数据是以页为......
  • mysql杀掉语句
    如何实现MySQL杀掉语句介绍MySQL的"杀掉语句"指的是终止正在执行的SQL语句,通常用来取消长时间运行或者错误的查询。作为一名经验丰富的开发者,我将指导你如何实现杀掉MySQL语句的步骤和相应的代码。流程下面是实现MySQL杀掉语句的步骤及相应代码的展示:步骤代码说明1......
  • mysql三表连接查询sql语句
    实现MySQL三表连接查询SQL语句的步骤在MySQL中,我们可以通过使用JOIN关键字来实现多个表的连接查询。具体而言,三表连接查询是指同时连接三张表,根据表之间的关联关系进行数据的查询。下面是实现MySQL三表连接查询SQL语句的步骤:步骤一:建立三张表在进行三表连接查询之前,首先需要建立......
  • mysql如何在一列后添加列
    项目方案:在MySQL表的一列后添加新列1.项目背景和目标在开发和维护数据库应用程序时,经常需要向已有的MySQL表中添加新的列。本项目旨在提供一个可靠和有效的解决方案,使开发人员能够在一列后添加新列,而无需重新创建表格或导致数据丢失。2.技术选型在这个项目中,我们将使用MySQL......
  • mysql如何在数据完全没有的情况下赋值
    在MySQL中,可以使用INSERTINTO语句向表中插入新的数据。当数据完全没有的情况下,我们可以通过INSERTINTO语句将数据赋值给表。首先,我们需要创建一个表来存储数据。可以使用CREATETABLE语句来创建一个新的表,并指定表的结构和字段。CREATETABLEmy_table(idINTPRIMARYKE......
  • SQLServer 查询语句指定排序规则(查询时区分大小写)
    SQLServer查询语句指定排序规则(查询时区分大小写)介绍可以使用COLLATE子句将字符表达式应用于某个排序规则。为字符文本和变量分配当前数据库的默认排序规则。为列引用分配列的定义排序规则。COLLATE定义数据库或表列的排序规则,或应用于字符串表达式时的排序规则强制转换......
  • 【Oracle】在PL/SQL中使用sql实现插入排序
    【Oracle】在PL/SQL中使用sql实现插入排序一般来说,SQL要排序的话直接使用orderby即可不一般来说,就是瞎搞,正好也可以巩固自己的数据结构基础,主要也发现没有人用SQL去实现这些算法(小声bb)使用SQL实现排序系列:使用SQL实现冒泡排序使用SQL实现选择排序以下是正文:规范:createor......
  • MySQL的表关系
    表关系(外键)什么是外键? 外键就是通过一个字段可以查询到另一张表上的内容为什么要有外键? """ 1、表的数据不够清晰,分不清表的具体用处 2、字段需要重复的写太浪费资源 3、兼容性很差,牵一发而动全身 """使用外键如何解决? 把一张表拆成两张表,每个表上面是自己独有......
  • MySQL的了解知识
    SQL注入问题importpymysql#连接MySQL服务端conn=pymysql.connect(host='127.0.0.1',port=3306,user='root',password='123',database='db8_3',charset='utf8',autocommit=True#针对增......