mysql存储过程如何利用临时表返回结果集

目录
  • 首先要声明的是
  • 测试示例
  • 真实需求,查找出所有用建单情况

首先要声明的是

1,游标的方法会很慢在mysql中,在oracle数据库中还可以,除非没有别的方法,一般不建议在mysql中使用游标,

2,不建议在mysql中拼接sql,会使存储过程显得很臃肿,可以使用or来动态判别传入的参数是否为空

and  ( TTB.office_id=输入参数 or  输入参数 is null  or 输入参数 = '')
and  ( TTB.office_id=IN_Office_id or  IN_Office_id is null  or IN_Office_id = '')

3,不建议使用临时表来存储多用户下经常查询的内容,比如报表

4,返回结果集更好的方法是直接链接多个表返回结果集即可,下面的示例虽然给以得到正确结果,

但代码臃肿,速度异常的慢,可以当个反面教材

5,优化后的存储过程:https://www.jb51.net/article/263729.htm

测试示例

BEGIN
		#创建一个临时表
        DROP TABLE if  exists user_temporary;
		create temporary table if not exists user_temporary
		(
				id	VARCHAR(64) primary key,#id
				user_name VARCHAR(20) #姓名

				) ;
         begin

           #定义 变量  接收id和姓名
           declare a VARCHAR(64);
           declare b VARCHAR(20);

           #这个用于处理游标到达最后一行的情况  

           DECLARE s int default 0;  

           #声明游标cursor_name(cursor_name是个多行结果集)  

           DECLARE cursor_name CURSOR FOR select id ,name     from user ;  

           #设置一个终止标记   

           DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET s=1;  

                #打开游标  

                OPEN cursor_name;  

                    #获取游标当前指针的记录,读取一行数据并传给变量a,b  

                    fetch  cursor_name into a,b;
                    #开始循环,判断是否游标已经到达了最后作为循环条件   

                    while s <> 1 do  

                            insert into user_temporary(id,user_name) values(a,b);
                            #读取下一行的数据  

                            fetch  cursor_name into a,b;  

                    end while;  

                 #关闭游标  

                 CLOSE cursor_name ;  

         #从临时表中拿到结果集
				SELECT  * from user_temporary;  

    #语句执行结束  

         end;

END

注意类型 为存储过程 procedure 不是存储函数function

运行结果:

真实需求,查找出所有用建单情况

BEGIN
        DROP TABLE if  exists user_temporary;
				create temporary table if not exists user_temporary
				(
						id	VARCHAR(64) primary key,id
						user_name VARCHAR(20) ,#姓名
						company_name VARCHAR(20) ,#所属公司
						worksheet_num INTEGER,			#机会点总数
						sign_worksheet_num INTEGER  ,#签单数量
						exchange_num INTEGER ,#填写交流记录次数
						sales_volume double(20,2) #销售额
					) ;
         begin

           #定义 变量
			declare a_id VARCHAR(64);
			declare b_user_name VARCHAR(20);
			declare c_company_name VARCHAR(20);
			declare d_worksheet_num int ;
			declare e_sign_worksheet_num int ;
			declare f_exchange_num int ;
			declare g_sales_volume double(20,2) ;

           #这个用于处理游标到达最后一行的情况  

           DECLARE s int default 0;  

           #声明游标cursor_name(cursor_name是个多行结果集)  

           DECLARE cursor_name CURSOR FOR
						select a.id ,a.name ,o.name AS company_name   from sys_user a  LEFT JOIN sys_office o on a.company_id =o.id;  

           #设置一个终止标记  

           DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET s=1;  

                #打开游标  

                OPEN cursor_name;  

                    #获取游标当前指针的记录,读取一行数据并传给变量a,b  

                    fetch  cursor_name into a_id,b_user_name ,c_company_name;
                    #开始循环,判断是否游标已经到达了最后作为循环条件   

                    while s <> 1 do  

                      #读取下一行的数据  

					#声明输入变量,以便在sql串中拼接

					set @userId=a_id;
					set @beginDate=begin_date;
					set @endDate=end_date;

					#收集总机会点 有if判断用拼接sql,然后再解析执行sql,
					set  @exesqlAll =CONCAT('SELECT count(1) into @handle_num FROM crm_worksheet  

										where  create_by=@userId and del_flag=0 ');

						IF begin_date is not null and begin_date !=''  THEN
						set		@exesqlAll =CONCAT(@exesqlAll,' AND TO_DAYS(create_date) >=TO_DAYS(@beginDate)');
						END IF;

						IF end_date is not null and end_date !='' THEN
						set		@exesqlAll =CONCAT(@exesqlAll,' AND TO_DAYS(create_date) <=TO_DAYS(@endDate)');
						END IF;

					prepare allWorksheet from @exesqlAll;	#解析sql
					execute allWorksheet;					#执行sql
					DEALLOCATE prepare allWorksheet;		#释放sql
					SET  d_worksheet_num  = @handle_num;	#变量赋值

					IF d_worksheet_num > 0 THEN

						set  @exesqlSign =CONCAT('SELECT count(1) into @sign_num FROM crm_worksheet  

										where  create_by=@userId and del_flag=0  and important_degree=''sys_basic_qian_shu_he_tong'' ');

							IF begin_date is not null and begin_date !=''  THEN
							set		@exesqlSign =CONCAT(@exesqlSign,' AND TO_DAYS(create_date) >=TO_DAYS(@beginDate)');
							END IF;

							IF end_date is not null and end_date !='' THEN
							set		@exesqlSign =CONCAT(@exesqlSign,' AND TO_DAYS(create_date) <=TO_DAYS(@endDate)');
							END IF;

						prepare signWorksheet from @exesqlSign;
						execute signWorksheet;
						DEALLOCATE prepare signWorksheet;
						SET  e_sign_worksheet_num  = @sign_num;

						#收集交流次数
						set  @exesqlExchange =CONCAT('SELECT  COUNT(1) into @exchange_num from crm_wkst_exchange_record  e LEFT JOIN
						crm_worksheet w on e.worksheet_no= w.worksheet_no where w.create_by=@userId and w.del_flag=0');

						IF begin_date is not null and begin_date !=''  THEN
						set		@exesqlExchange =CONCAT(@exesqlExchange,' AND TO_DAYS(w.create_date) >=TO_DAYS(@beginDate)');
						END IF;

						IF end_date is not null and end_date !='' THEN
						set		@exesqlExchange =CONCAT(@exesqlExchange,' AND TO_DAYS(w.create_date) <=TO_DAYS(@endDate)');
						END IF;

						prepare exchangeWorksheet from @exesqlExchange;
						execute exchangeWorksheet;
						DEALLOCATE prepare exchangeWorksheet;
						SET  f_exchange_num  = @exchange_num;

						#收集销售额
						set  @exesqlSales =CONCAT('SELECT		 (@sumSalary := @sumSalary + solution) AS count   into @sales_num   FROM crm_worksheet cw , (SELECT @sumSalary :=	 0) b
									WHERE  cw.create_by=@userId and important_degree=''sys_basic_qian_shu_he_tong'' and cw.del_flag=0 ORDER BY   count desc limit 1 ');

						IF begin_date is not null and begin_date !=''  THEN
						set		@exesqlExchange =CONCAT(@exesqlExchange,' AND TO_DAYS(cw.create_date) >=TO_DAYS(@beginDate)');
						END IF;

						IF end_date is not null and end_date !='' THEN
						set		@exesqlExchange =CONCAT(@exesqlExchange,' AND TO_DAYS(cw.create_date) <=TO_DAYS(@endDate)');
						END IF;

						prepare salesWorksheet from @exesqlSales;
						execute salesWorksheet;
						DEALLOCATE prepare salesWorksheet;
						SET  g_sales_volume  = @sales_num;

					ELSE
							 SET e_sign_worksheet_num=0; SET f_exchange_num=0; SET g_sales_volume=0;

					END IF;

                    insert into user_temporary(id,user_name,company_name,sign_worksheet_num,exchange_num,worksheet_num,sales_volume)
																	values(a_id,b_user_name,c_company_name,e_sign_worksheet_num,f_exchange_num,d_worksheet_num,g_sales_volume);  #插入临时表

                             fetch  cursor_name into a_id,b_user_name ,c_company_name; 

                    end while;  

                 #关闭游标  

                 CLOSE cursor_name ;  

				#从临时表中查出结果集
				set @userIdInput=user_id;
				set  @exesqlResult =CONCAT('SELECT  user_name,company_name,sign_worksheet_num,exchange_num,worksheet_num,sales_volume  from user_temporary');

				IF user_id  is not null and user_id !=''  THEN
					set		@exesqlResult =CONCAT(@exesqlResult,'  where id = @userIdInput');
					END IF;

				prepare resultUser from @exesqlResult;
					execute resultUser;
				DEALLOCATE prepare resultUser;

    #语句执行结束  

         end;

END

运行结果

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • 浅谈Mysql在什么情况下会使用内部临时表

    union执行 为了便于分析,使用一下sql来进行举例 CREATE TABLE t1 ( id INT PRIMARY KEY, a INT, b INT, INDEX ( a ) ); delimiter ;; CREATE PROCEDURE idata ( ) BEGIN DECLARE i INT; SET i = 1; WHILE ( i <= 1000 ) DO INSERT INTO t1 VALUES ( i, i, i ); SET i = i + 1; END WHILE;

  • MySQL 临时表的原理以及优化方法

    目录 1 临时表 2 union临时表优化 3 group by临时表优化 1 临时表 sort buffer.内存临时表和join buffer,这三个数据结构都是用来存放语句执行过程中的中间数据,以辅助SQL语句的执行的.其中,在排序的时候用到了sort buffer,在使用join语句的时候用到了join buffer. 而使用临时表的时候,Explain的Extra字段中具有Using temporary标记.union.group by.distinct等等查询都有可能使用到临时表.

  • mysql临时表插入数据方式

    目录 mysql临时表插入数据 临时表 mysql中临时表(TEMPORARY) 语法 功能 检查是否存在临时表 与MEMORY比较 mysql临时表插入数据 临时表 1.在数据库断开连接的时候会自动删除临时表. create temporary table IF NOT EXISTS client.getstucou( type_id int )Engine=InnoDB default charset utf8; 注意:在存储过程中创建了临时表的情况的话,在外面使用查询语句是找不到这张表的.

  • MySQL为什么临时表可以重名

    目录 临时表的特性 临时表的应用 为什么临时表可以重名? 临时表和主备复制 主库上不同的线程创建同名的临时表是没关系的,但是传到备库执行是怎么处理的呢? 今天我们就从这个问题说起:临时表有哪些特征,适合哪些场景? 这里,我需要先帮你厘清一个容易误解的问题:有的人可能会认为,临时表就是内存表.但是,这两个概念可是完全不同的. 内存表,指的是使用Memory引擎的表,建表语法是create table …engine=memory.**这种表的数据都保存在内存里,系统重启的时候会被清空,但是表结构还

  • MySQL内部临时表的具体使用

    目录 UNION 表初始化 执行语句 UNION RESULT UNION ALL GROUP BY 内存充足 执行语句 执行过程 排序过程 ORDER BY NULL 内存不足 执行语句 优化方案 优化索引 直接排序 执行过程 对比DISTINCT 小结 参考资料 UNION UNION语义:取两个子查询结果的并集,重复的行只保留一行 表初始化 CREATE TABLE t1(id INT PRIMARY KEY, a INT, b INT, INDEX(a)); DELIMITER ;; C

  • MySQL临时表的使用方法详解

    目录 1. 写在前面的话 2. 临时表的使用 2.1 创建一个只存放亚洲国家信息的临时表 2.1.1 创建临时表 2.1.2 向临时表里写数据 2.2 在查询过程中直接创建临时表 2.3 查询临时表中的数据 2.4 删除临时表 3. 以上操作的全部代码 总结 1. 写在前面的话 在开发数据库时,特别是写存储过程,遇到比较复杂的需求,使用临时表可以简化很多逻辑.曾经在一家互联网金融公司供职,公司数据组团队做数据清洗,写SQL脚本时,一个查询语句可以套到数层查询,甚至十几层.看起来几百行上千行的脚本

  • 使用MySQL实现select into临时表的功能

    目录 MySQL select into临时表 select into 临时表 create 临时表 mysql临时表(可以将查询结果存在临时表中) 创建临时表可以将查询结果寄存 mysql把select结果保存为临时表,有2种方法 MySQL select into临时表 最近在编写sql语句时,遇到两次将数据放temp表,然后将两次的temp表进行inner join,再供后续insert数据时使用的场景. 写完后发现执行耗时较长,需要优化,于是将一条长长的sql语句拆分成一个sql脚本,用

  • mysql存储过程如何利用临时表返回结果集

    目录 首先要声明的是 测试示例 真实需求,查找出所有用建单情况 首先要声明的是 1,游标的方法会很慢在mysql中,在oracle数据库中还可以,除非没有别的方法,一般不建议在mysql中使用游标, 2,不建议在mysql中拼接sql,会使存储过程显得很臃肿,可以使用or来动态判别传入的参数是否为空 and  ( TTB.office_id=输入参数 or  输入参数 is null  or 输入参数 = '') and  ( TTB.office_id=IN_Office_id or  IN_

  • Oracle中返回结果集的存储过程分享

    Oracle不像SQLServer那样在存储过程中用Select就可以返回结果集,而是通过Out型的参数进行结果集返回的.实际上是利用REF CURSOR 复制代码 代码如下: --procedure返回记录集: ----------------------声明一个Package-------------- CREATE OR REPLACE PACKAGE pkg_test AS TYPEmyrctypeIS REF CURSOR; PROCEDURE get_r(p_id NUMBER,p_

  • 为什么在存储过程中用OLEDB方式不能返回记录集

    为什么在存储过程中用OLEDB方式不能返回记录集?我曾写过一段程序,是对临时表操作的(主要功能是取出每种分类的TOP10条记录).该存储过程使用ODBC连接数据库时正常,能够得到正确的结果.但在使用oledb方式连接时,却不能返回记录集,而一旦操作返回记录集时就出现错误提示:ADODB.Recordset 错误 '800a0e78' The operation requested by the application is not allowed if the object is closed.

  • asp sqlserver 执行存储过程返回记录集报对象关闭时不允许操作

    如果要得到返回值,需要用Command的方法. 首先说明,返回值有两种.一种是在存储过程中直接return一个值,就象C和VB的函数返回值那样:另一种是可以返回多个值,存储这些值的变量名称需要在调用参数中先行指定. 这个例子要处理多种参数,输入参数,输出参数,返回记录集以及一个直接返回值(够全了吧?) 存储过程如下: 复制代码 代码如下: use pubs GO -- 建立存储过程 create procedure sp_PubsTest -- 定义三个参数变量,注意第三个,特别标记是用于输出

  • mybatis调用mysql存储过程(返回参数,单结果集,多结果集)

    目录 一.接收一个返回值 注意事项: 存储过程主要分成三类: 二.接收list结果集 三.返回多个结果集 四.第二种配置也可以 一.接收一个返回值 使用Map接收返回参数,output参数放在传入的param中 创建表 DROP TABLE IF EXISTS `demo`; CREATE TABLE `demo` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`

  • mysql存储过程 返回 list结果集方式

    目录 mysql存储过程 返回 list结果集 思路 mysql存储过程和存储函数练习 存储过程和存储函数语法 存储函数 案例演示 mysql存储过程 返回 list结果集 思路 直接链接多个表返回结果集即可,先写成普通的sql调整好,不要输入参数,再写成存储过程, 不要用游标,否则会把你慢哭的 BEGIN DECLARE In_StartTime VARCHAR(64); DECLARE In_StopTime VARCHAR(64); DECLARE IN_User_id VARCHAR(6

  • PHP调用MySQL存储过程并返回值的方法

    本文实例讲述了php中调用执行mysql存储过程然后返回由存储过程返回的值,分享给大家供大家参考.具体分析如下: 调用存储过程的方法. a.如果存储过程有 IN/INOUT参数,声明一个变量,输入参数给存储过程,该变量是一对,一个php变量,也可以不必,只是没有php变量时,没有办法进行动态输入,一个Mysql变量. b.如果存储过程有OUT变量,声明一个Mysql变量,mysql变量的声明比较特殊,必须让mysql服务器知道此变量的存在,其实也就是执行一条mysql语句,入set @mysql

  • Mysql 存储过程中使用游标循环读取临时表

    游标 游标(Cursor)是用于查看或者处理结果集中的数据的一种方法.游标提供了在结果集中一次一行或者多行前进或向后浏览数据的能力. 游标的使用方式 定义游标:Declare 游标名称 CURSOR for table;(table也可以是select出来的结果集) 打开游标:Open 游标名称; 从结果集获取数据到变量:fetch 游标名称 into field1,field2; 执行语句:执行需要处理数据的语句 关闭游标:Close 游标名称; BEGIN # 声明自定义变量 declare

  • sqlserver2005利用临时表和@@RowCount提高分页查询存储过程性能示例分享

    最近发现现有框架的通用查询存储过程的性能慢,于是仔细研究了下代码: 复制代码 代码如下: Alter PROCEDURE [dbo].[AreaSelect]    @PageSize int=0,    @CurrentPage int=1,    @Identifier int=NULL,    @ParentId int=NULL,    @AreaLevel int=NULL,    @Children int=NULL,    @AreaName nvarchar(50)=NULL, 

  • Java调用MySQL存储过程并获得返回值的方法

    本文实例讲述了Java调用MySQL存储过程并获得返回值的方法.分享给大家供大家参考.具体如下: private void empsInDept(Connection myConnect, int deptId) throws SQLException { CallableStatement cStmt = myConnect.prepareCall("{CALL sp_emps_in_dept(?)}"); cStmt.setInt(1, deptId); cStmt.execute

随机推荐