Mysql存储过程(六)——存储过程中使用临时表
2014-06-02 22:07
651 查看
Mysql 不支持数组。但有时候需要组合几张表的数据,在存储过程中,经过比较复杂的运算获取结果直接输出给调用方,比如符合条件的几张表的某些字段的组合计算。 Mysql 临时表可以解决这个问题。
临时表:只有在当前连接情况下, TEMPORARY 表才是可见的。当连接关闭时, TEMPORARY 表被自动取消。这意味着两个不同的连接可以使用相同的临时表名称,同时两个临时表不会互相冲突,也不与原有的同名的非临时表冲突。(原有的表被隐藏,直到临时表被取消时为止。)必须拥有 CREATE TEMPORARY TABLES 权限,才能创建临时表。可以通过指定 ENGINE|TYPE = MEMORY; 来指定创建内存临时表。
如果表已存在,则使用关键词 IF NOT EXISTS 可以防止发生错误。注意,原有表的结构与 CREATE TABLE 语句中表示的表的结构是否相同,这一点没有验证。注释:如果在 CREATE TABLE...SELECT 语句中使用 IF NOT EXISTS ,则不论表是否已存在,由 SELECT 部分选择的记录都会被插入。
DROP TEMPORARY TABLE 语句只取消 TEMPORARY 表,语句不会终止正在进行中的事务。在采用连接池的情况下,为防止多次 CREATE 、 DROP TEMPORARY TABLE 带来的性能瓶颈,可以使用 CREATE IF NOT EXISTS + TRUNCATE TABLE 的方式来提升性能。
临时表支持主键、索引指定。在连接非临时表查询可以利用指定主键或索引来提升性能。
sql code 6-1:
[c-sharp] view plaincopy
CREATE PROCEDURE sp_test_tt(IN i_chars VARCHAR(50),OUT o_counts BIGINT)
BEGIN
create temporary table if not exists tmpTable – 不存在则创建临时表
(
objChk varchar(255) primary key,
ModelName varchar(50),
Operator varchar(500),
PModelName varchar(50)
);
truncate TABLE tmpTable; -- 使用前先清空临时表。
insert into tmpTable values(i_chars,i_chars,i_chars,i_chars);
insert into tmpTable values(i_chars,i_chars,i_chars,i_chars); -- 语句1
select * from tmpTable; -- 语句2
select count(*) into o_counts from tmpTable; -- 语句3
END;
上述代码语句 1 返回临时表中所有数据,语句 2 将总记录数写入输出参数。 truncate 语句放在 create 之后,而不是整个存储过程最后,原因在于随后的语句 1 插入同样的值,二临时表 PK 校验将产生一个错误,则存储过程最终异常结束。综合异常处理,可以如下修改,以在每次存储过程调用完毕后清除临时表。
sql code 6-2:
[c-sharp] view plaincopy
CREATE PROCEDURE sp_test_tt(IN i_chars VARCHAR(50),OUT o_counts BIGINT)
BEGIN
create temporary table if not exists tmpTable
(
objChk varchar(255) primary key,
ModelName varchar(50),
Operator varchar(500),
PModelName varchar(50)
) ENGINE = MEMORY;
begin
declare exit handler for sqlwarning,NOT FOUND,SQLEXCEPTION set o_counts=-1;
insert into tmpTable values(i_chars,i_chars,i_chars,i_chars);
select * from tmpTable; -- 语句1
select count(*) into o_counts from tmpTable;
end;
truncate TABLE tmpTable; -- 语句2
END;
虽然上述代码语句 2 最后 truncate table 清空了全部临时表数据,但前面语句 1 select 的数据结果集不会被清除。已通过 java 程序验证。
临时表可以解决二维数组输出的问题。但是,大批量的数据插入只能由程序采用循环来做。某些特殊情况下的输入数组,例如选择好的一组待删除数据的 ID 的输入,也只能利用循环来做。临时表也不适用于需要三维数组的情况。
DELIMITER //
CREATE PROCEDURE M()
BEGIN
DECLARE NAME1 VARCHAR(10);
DECLARE AGE1 INT;
DECLARE NUM INT;
DECLARE FLAG INT;
select count(*) into NUM from user;
CREATE TEMPORARY TABLE IF NOT EXISTS T1
( Id int not null primary key auto_increment,
name varchar(11),age int
)ENGINE=MEMORY;
begin
declare cur1 cursor for select userName,userAge from user;
declare CONTINUE HANDLER FOR NOT FOUND SET FLAG=1;
SET FLAG=0;
OPEN cur1;
FETCH cur1 into NAME1,AGE1;
WHILE(FLAG!=1) DO
INSERT INTO T1(name,age) values(NAME1,AGE1);
FETCH cur1 into NAME1,AGE1;
END WHILE;
SELECT * FROM T1;
end;
TRUNCATE TABLE T1;
END;//
Query OK, 0 rows affected
mysql> CALL M(@N);
+----+--------+-----+
| Id | name | age |
+----+--------+-----+
| 1 | summer | 100 |
| 2 | 飞鸟 | 20 |
| 3 | 佳佳 | 30 |
| 4 | 佳佳 | 30 |
+----+--------+-----+
4 rows in set
Query OK, 0 rows affected
mysql> SELECT @N;
+----+
| @N |
+----+
| 4 |
+----+
1 row in set
临时表:只有在当前连接情况下, TEMPORARY 表才是可见的。当连接关闭时, TEMPORARY 表被自动取消。这意味着两个不同的连接可以使用相同的临时表名称,同时两个临时表不会互相冲突,也不与原有的同名的非临时表冲突。(原有的表被隐藏,直到临时表被取消时为止。)必须拥有 CREATE TEMPORARY TABLES 权限,才能创建临时表。可以通过指定 ENGINE|TYPE = MEMORY; 来指定创建内存临时表。
如果表已存在,则使用关键词 IF NOT EXISTS 可以防止发生错误。注意,原有表的结构与 CREATE TABLE 语句中表示的表的结构是否相同,这一点没有验证。注释:如果在 CREATE TABLE...SELECT 语句中使用 IF NOT EXISTS ,则不论表是否已存在,由 SELECT 部分选择的记录都会被插入。
DROP TEMPORARY TABLE 语句只取消 TEMPORARY 表,语句不会终止正在进行中的事务。在采用连接池的情况下,为防止多次 CREATE 、 DROP TEMPORARY TABLE 带来的性能瓶颈,可以使用 CREATE IF NOT EXISTS + TRUNCATE TABLE 的方式来提升性能。
临时表支持主键、索引指定。在连接非临时表查询可以利用指定主键或索引来提升性能。
sql code 6-1:
[c-sharp] view plaincopy
CREATE PROCEDURE sp_test_tt(IN i_chars VARCHAR(50),OUT o_counts BIGINT)
BEGIN
create temporary table if not exists tmpTable – 不存在则创建临时表
(
objChk varchar(255) primary key,
ModelName varchar(50),
Operator varchar(500),
PModelName varchar(50)
);
truncate TABLE tmpTable; -- 使用前先清空临时表。
insert into tmpTable values(i_chars,i_chars,i_chars,i_chars);
insert into tmpTable values(i_chars,i_chars,i_chars,i_chars); -- 语句1
select * from tmpTable; -- 语句2
select count(*) into o_counts from tmpTable; -- 语句3
END;
上述代码语句 1 返回临时表中所有数据,语句 2 将总记录数写入输出参数。 truncate 语句放在 create 之后,而不是整个存储过程最后,原因在于随后的语句 1 插入同样的值,二临时表 PK 校验将产生一个错误,则存储过程最终异常结束。综合异常处理,可以如下修改,以在每次存储过程调用完毕后清除临时表。
sql code 6-2:
[c-sharp] view plaincopy
CREATE PROCEDURE sp_test_tt(IN i_chars VARCHAR(50),OUT o_counts BIGINT)
BEGIN
create temporary table if not exists tmpTable
(
objChk varchar(255) primary key,
ModelName varchar(50),
Operator varchar(500),
PModelName varchar(50)
) ENGINE = MEMORY;
begin
declare exit handler for sqlwarning,NOT FOUND,SQLEXCEPTION set o_counts=-1;
insert into tmpTable values(i_chars,i_chars,i_chars,i_chars);
select * from tmpTable; -- 语句1
select count(*) into o_counts from tmpTable;
end;
truncate TABLE tmpTable; -- 语句2
END;
虽然上述代码语句 2 最后 truncate table 清空了全部临时表数据,但前面语句 1 select 的数据结果集不会被清除。已通过 java 程序验证。
临时表可以解决二维数组输出的问题。但是,大批量的数据插入只能由程序采用循环来做。某些特殊情况下的输入数组,例如选择好的一组待删除数据的 ID 的输入,也只能利用循环来做。临时表也不适用于需要三维数组的情况。
DELIMITER //
CREATE PROCEDURE M()
BEGIN
DECLARE NAME1 VARCHAR(10);
DECLARE AGE1 INT;
DECLARE NUM INT;
DECLARE FLAG INT;
select count(*) into NUM from user;
CREATE TEMPORARY TABLE IF NOT EXISTS T1
( Id int not null primary key auto_increment,
name varchar(11),age int
)ENGINE=MEMORY;
begin
declare cur1 cursor for select userName,userAge from user;
declare CONTINUE HANDLER FOR NOT FOUND SET FLAG=1;
SET FLAG=0;
OPEN cur1;
FETCH cur1 into NAME1,AGE1;
WHILE(FLAG!=1) DO
INSERT INTO T1(name,age) values(NAME1,AGE1);
FETCH cur1 into NAME1,AGE1;
END WHILE;
SELECT * FROM T1;
end;
TRUNCATE TABLE T1;
END;//
DELIMITER // CREATE PROCEDURE M(OUT n INT) BEGIN DECLARE NAME1 VARCHAR(10); DECLARE AGE1 INT; DECLARE NUM INT; DECLARE FLAG INT; DECLARE LEN INT; select count(*) into NUM from user; CREATE TEMPORARY TABLE IF NOT EXISTS T1 ( Id int not null primary key auto_increment, name varchar(11),age int )ENGINE=MEMORY; begin declare cur1 cursor for select userName,userAge from user; declare CONTINUE HANDLER FOR NOT FOUND SET FLAG=1; SET FLAG=0; SET n=0; SET LEN=NUM/10; OPEN cur1; FETCH cur1 into NAME1,AGE1; WHILE(FLAG!=1) DO IF(n%(LEN+1)=0) THEN INSERT INTO T1(name,age) values(NAME1,AGE1); END IF; SET n=n+1; FETCH cur1 into NAME1,AGE1; END WHILE; SELECT * FROM T1; end; TRUNCATE TABLE T1; END;//mysql> SET @N=0;
Query OK, 0 rows affected
mysql> CALL M(@N);
+----+--------+-----+
| Id | name | age |
+----+--------+-----+
| 1 | summer | 100 |
| 2 | 飞鸟 | 20 |
| 3 | 佳佳 | 30 |
| 4 | 佳佳 | 30 |
+----+--------+-----+
4 rows in set
Query OK, 0 rows affected
mysql> SELECT @N;
+----+
| @N |
+----+
| 4 |
+----+
1 row in set
相关文章推荐
- Mysql存储过程(六)——存储过程中使用临时表
- Mysql存储过程(六)——存储过程中使用临时表
- mysql存储过程中使用临时表
- MySQL存储过程详解 mysql 存储过程--完全可以当手册使用呢~
- mysql存储过程中使用临时表
- Mysql存储过程中使用临时表
- Mysql存储过程------存储过程的基本概念和基本使用方法
- mysql 存储过程示例,有参有返回值,使用到了判断,循环,游标,临时表,事务
- mysql 存储过程中使用游标中使用临时表可以替代数组效果
- [mysql存储过程] mysql存储过程使用详解
- 存储过程中使用临时表.
- 临时表操作的一些见解(解决了我在存储过程中使用临时表的困惑)
- MySQL 存储过程和"Cursor"的使用方法
- 使用MySQL存储过程创建动态交叉表(3)
- 存储过程介绍及asp存储过程的使用
- 使用MySQL存储过程连续插入多条记录
- mysql存储过程学习及java调用存储过程
- mysql存储过程学习及java调用存储过程(转载)
- 存储过程内建临时表和临时函数,合并一个由存储过程返回的表
- 存储过程介绍及asp存储过程的使用