×

存储过程创建临时表

存储过程创建临时表(为什么在mysql存储过程中创建的临时表不能)

admin admin 发表于2023-09-28 06:37:33 浏览33 评论0

抢沙发发表评论

本文目录

为什么在mysql存储过程中创建的临时表不能

提到MySQL临时表,我们都很熟悉了,一般来说,分为两类:

1. MySQL 临时表引擎,名字叫做 Memory。比如

create table tmp1(id int, str1 varchar(100) ) engine = memory;

由参数max_heap_table_size 来控制,超过报错。

2. 非临时表的引擎,这里又分为两类:

  • 用户自定义的临时表,比如:

  • create temporary table (id int, str1 varchar(100) );
  • SQL执行过程中产生的内部临时表,比如:UNION , 聚合类ORDER BY,派生表,大对象字段的查询,子查询或者半连接的固化等等场景。

  • 那么这两种临时表的计数器通常用 show global status like ’%tmp_%tables%’ 来查看。比如

  • mysql》 show status like ’%tmp_%tables%’;``+-------------------------+-------+``| Variable_name           | Value |``+-------------------------+-------+``| Created_tmp_disk_tables | 0     |``| Created_tmp_tables      | 0     |``+-------------------------+-------+``2 rows in set (0.00 sec)
  • 以上结果分别代表,只创建磁盘上的临时表计数以及临时表的总计数。这两个计数器由参数 tmp_table_size 和 max_heap_table_size 两个取最小值来控制。

    那在 MySQL 5.7 之前,这个 SQL 运行中产生的临时表是 MYISAM,而且只能是 MYISAM。那 MySQL 从 5.7 开始提供了参数 Internal_tmp_mem_storage_engine 来定义内部的临时表引擎,可选值为 MYISAM 和 INNODB 。当然这里我们选择 INNODB 。并且把内部的临时表默认保存在临时表空间 ibtmp1 (可以用参数 innodb_temp_data_file_path 设置大小以及步长等)下。当然这里我们得控制下 ibtmp1 的大小,要不然一个烂SQL就把磁盘整爆了。

    但是MySQL 5.7 之前都没有解决如下问题:

  • VARCHAR的变长存储。那就是如果临时表的字段定义是 VARCHAR(200),那么映射到内存里处理的字段变为CHAR(200)。假设 VARCHAR(200) 就存里一个字符 “Y“, 那岂不是很大的浪费。

  • 大对象的默认磁盘存储,比如 TEXT,BLOB, JSON等,不管里面存放了啥,直接转化为磁盘存储。

  • MySQL 8.0 开始,专门实现了一个临时表的引擎 TempTable , 解决了 VARCHAR字段的边长存储以及大对象的内存存储。由变量 interal_tmp_mem_storage_engine来控制,可选值为 TempTable(默认)和 Memory;新引擎的大小由参数temp_table_max_ram 来控制,默认为1G。超过了则存储在磁盘上(ibtmp1)。并且计数器由性能字典的表 memory_summary_global_by_event_name 来存储。

  • mysql》 SELECT * FROM performance_schema. memory_summary_global_by_event_name WHERE event_name like ’%temptable%’G*************************** 1. row ***************************                  EVENT_NAME: **memory/temptable/physical_disk**                 COUNT_ALLOC: 0                  COUNT_FREE: 0   SUM_NUMBER_OF_BYTES_ALLOC: 0    SUM_NUMBER_OF_BYTES_FREE: 0              LOW_COUNT_USED: 0          CURRENT_COUNT_USED: 0             HIGH_COUNT_USED: 0    LOW_NUMBER_OF_BYTES_USED: 0CURRENT_NUMBER_OF_BYTES_USED: 0   HIGH_NUMBER_OF_BYTES_USED: 0*************************** 2. row ***************************                  EVENT_NAME: **memory/temptable/physical_ram**                 COUNT_ALLOC: 1                  COUNT_FREE: 0   SUM_NUMBER_OF_BYTES_ALLOC: 1048576    SUM_NUMBER_OF_BYTES_FREE: 0              LOW_COUNT_USED: 0          CURRENT_COUNT_USED: 1             HIGH_COUNT_USED: 1    LOW_NUMBER_OF_BYTES_USED: 0CURRENT_NUMBER_OF_BYTES_USED: 1048576   HIGH_NUMBER_OF_BYTES_USED: 10485762 rows in set (0.03 sec)
  • 以上 memory/temptable/physical_disk 代表放入磁盘上的临时表计数情况。

    memory/temptable/physical_ram 代表放入内存的临时表计数情况。

    那总结下MySQL 8.0 引入的 TempTable 引擎:

  • 默认内部临时表引擎。

  • 支持变长字符类型的实际存储。

  • 设置变量 temp_table_max_ram 来控制实际存储内存区域大小。

sql如何创建临时表

网上其实很多相关文章,你可以搜一下,并不一定需要在这里提问。转帖一篇给你吧drop table #Tmp --删除临时表#Tmpcreate table #Tmp --创建临时表#Tmp( ID int IDENTITY (1,1) not null, --创建列ID,并且每次新增一条记录就会加1 WokNo varchar(50), primary key (ID) --定义ID为临时表#Tmp的主键 );Select * from #Tmp --查询临时表的数据truncate table #Tmp --清空临时表的所有数据和约束相关例子:Declare @Wokno Varchar(500) --用来记录职工号Declare @Str NVarchar(4000) --用来存放查询语句Declare @Count int --求出总记录数 Declare @i intSet @i = 0 Select @Count = Count(Distinct(Wokno)) from #TmpWhile @i 《 @Count Begin Set @Str = ’Select top 1 @Wokno = WokNo from #Tmp Where id not in (Select top ’ + Str(@i) + ’id from #Tmp)’ Exec Sp_ExecuteSql @Str,N’@WokNo Varchar(500) OutPut’,@WokNo Output Select @WokNo,@i --一行一行把职工号显示出来 Set @i = @i + 1 End临时表可以创建本地和全局临时表。本地临时表仅在当前会话中可见;全局临时表在所有会话中都可见。本地临时表的名称前面有一个编号符 (#table_name),而全局临时表的名称前面有两个编号符 (##table_name)。SQL 语句使用 CREATE TABLE 语句中为 table_name 指定的名称引用临时表:CREATE TABLE #MyTempTable (cola INT PRIMARY KEY)INSERT INTO #MyTempTable VALUES (1)如果本地临时表由存储过程创建或由多个用户同时执行的应用程序创建,则 SQL Server 必须能够区分由不同用户创建的表。为此,SQL Server 在内部为每个本地临时表的表名追加一个数字后缀。存储在 tempdb 数据库的 sysobjects 表中的临时表,其全名由 CREATE TABLE 语句中指定的表名和系统生成的数字后缀组成。为了允许追加后缀,为本地临时表指定的表名 table_name 不能超过 116 个字符。除非使用 DROP TABLE 语句显式除去临时表,否则临时表将在退出其作用域时由系统自动除去:当存储过程完成时,将自动除去在存储过程中创建的本地临时表。由创建表的存储过程执行的所有嵌套存储过程都可以引用此表。但调用创建此表的存储过程的进程无法引用此表。所有其它本地临时表在当前会话结束时自动除去。全局临时表在创建此表的会话结束且其它任务停止对其引用时自动除去。任务与表之间的关联只在单个 Transact-SQL 语句的生存周期内保持。换言之,当创建全局临时表的会话结束时,最后一条引用此表的 Transact-SQL 语句完成后,将自动除去此表。 在存储过程或触发器中创建的本地临时表与在调用存储过程或触发器之前创建的同名临时表不同。如果查询引用临时表,而同时有两个同名的临时表,则不定义针对哪个表解析该查询。嵌套存储过程同样可以创建与调用它的存储过程所创建的临时表同名的临时表。嵌套存储过程中对表名的所有引用都被解释为是针对该嵌套过程所创建的表,例如:CREATE PROCEDURE Test2ASCREATE TABLE #t(x INT PRIMARY KEY)INSERT INTO #t VALUES (2)SELECT Test2Col = x FROM #tGOCREATE PROCEDURE Test1ASCREATE TABLE #t(x INT PRIMARY KEY)INSERT INTO #t VALUES (1)SELECT Test1Col = x FROM #tEXEC Test2GOCREATE TABLE #t(x INT PRIMARY KEY)INSERT INTO #t VALUES (99)GOEXEC Test1GO下面是结果集:(1 row(s) affected)Test1Col ----------- 1 (1 row(s) affected)Test2Col ----------- 2 当创建本地或全局临时表时,CREATE TABLE 语法支持除 FOREIGN KEY 约束以外的其它所有约束定义。如果在临时表中指定 FOREIGN KEY 约束,该语句将返回警告信息,指出此约束已被忽略,表仍会创建,但不具有 FOREIGN KEY 约束。在 FOREIGN KEY 约束中不能引用临时表。考虑使用表变量而不使用临时表。当需要在临时表上显式地创建索引时,或多个存储过程或函数需要使用表值时,临时表很有用。通常,表变量提供更有效的查询处理。

SQL 存储过程和在存储过程中创建临时表

把你所有涉及的表自段发上来你这样怎么给你写啊ha是哪个表的自段啊需求明确了给你写才20分也太少了吧这个工作量可不小哦想当初我给人写这么左右的存储过程拿了500块人民币呢呢呵呵!建立临时表只是在表的前面加一个#,其它都舆建立实表相同,建立过程我相信你都知道了,就不用我多说了Egg:createtable#temp(idint,namevarchar(50))

oracle中,存储过程建的临时表

create table tmp_临时表 as select * from 表名 ;// 这边是创建临时表再将数据添加到临时表insert into tmp_临时表 select * from 表名 ; // 和上面的一样,但是这个是临时表已经存在新增数据

关于在存储过程中建立临时表

你试过了吗? 这样建是允许的!不过这样建的表属于本地临时表。当存储过程完成时,将自动删除在存储过程中创建的本地临时表。 可能是被删了你没看到--------CREATE PROCEDURE dbo.Test2ASCREATE TABLE #t(x INT PRIMARY KEY);INSERT INTO #t VALUES (2);SELECT Test2Col = x FROM #t;GOCREATE PROCEDURE dbo.Test1ASCREATE TABLE #t(x INT PRIMARY KEY);INSERT INTO #t VALUES (1);SELECT Test1Col = x FROM #t;EXEC Test2;GOCREATE TABLE #t(x INT PRIMARY KEY);INSERT INTO #t VALUES (99);GOEXEC Test1;GO这是个例子你可以运行了看看结果!

在存储过程中创建临时表,并对临时表进行操作!在线等答案!

创建临时表与正常表一样,操作也一样。只是不用删除,执行完成后就自动没有了 CREATE TABLE #TMP(FIELD1 INT,FIELD2 VARCHAR(30)) 或 CREATE TABLE ##TMP(FIELD1 INT,FIELD2 VARCHAR(30))