SQL 创建一个临时表#tabletemp 里面有两个字段“cn”和“dt”分别用来存储另一个表的字段名和数据类型。 50

假设这个表里面第一条数据分别是:USERID和intdeclare@achar(10)declare@bchar(10)selecttop1@a=cn,@b=dtfrom... 假设这个表里面第一条数据分别是:USERID 和 intdeclare @a char(10)declare @b char(10)select top 1 @a=cn,@b=dt from #tabletempselect @a,@b --此处输出应该是 USERID,int问题如下:如何根据cn字段的值(USERID 对应dt字段的值是int),去声明一个变量为select @b(此处输出 int)的类型?if 1=1则声明一个变量@c 数据类型为@b declare @c @b --(此处只是为了说明问题,实际运行报错)此处应随着变量@a值的改变而确定@c的数据类型。本例中@b的值是int型;假如@b的值是char型,则@c应该自动随着@b的值而改变数据类型为char。我想问一下怎么实现自动声明一个变量的数据类型在不同条件下可能为int、也可能为char,随着条件不同而不同?(可能描述的比较乱,配合着图片更能说明问题,见谅) 展开
 我来答
爱可生云数据库
2020-05-25 · MySQL开源数据库领先者
爱可生云数据库
爱可生,金融级开源数据库和数据云服务整体解决方案提供商;优秀的开源数据库技术,企业级数据处理技术整体解决方案提供商;私有云数据库云服务市场整体解决方案提供商。
向TA提问
展开全部

提到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 来控制实际存储内存区域大小。

鬼谷子教主
2016-10-27 · TA获得超过2496个赞
知道大有可为答主
回答量:1996
采纳率:88%
帮助的人:562万
展开全部
1、一般来说,使用动态SQL语句(拼装SQL)。
DECLARE @vSQL VarChar(max)
SET @vSQL = '...'
...
EXEC(@vSQL)

2、但我有点怀疑你这个设计方案本身并不合虚悔念理。
也许描述一下原始需求差困(而不是你前纯这个实现方案的问题),可以更好地帮助到你。
追问
这个问题的起因其实只是工作中碰到的一个小问题引起的,为了以后方便所以才用心看了一下。本质问题是,知道某个表的一个已知数值,但是不知道具体字段。要找出这个数值在这个表中属于哪一个字段?----方便查找字段。
追答

咱不求分:)

1、访问DB的元数据,得到该表的字段列表(其实也能得到数据类型)

DECLARE cur_ CURSOR FOR
SELECT name AS  FieldName
FROM sys.columns C
WHERE object_name(object_id) = 'TableName' 
--AND ... -- 安全些的话,控制某些类型的字段不参与.如Image

2、使用游标,根据类型来动态生成查找语句。

- 最简单的方法,就是转换成字符串

SET @sFind = Quotename('%' + CAST @Find AS VarChar(100)) + '%', '''')

OPEN cur_
FETCH NEXT FROM cur_ INTO ...
WHILE @@FETCH_STATUS = 0
BEGIN
    SET @sSQL = N'SELECT *
    FROM Table
    WHERE CAST(' + @FieldName + ' AS VarChar(100 ) LIKE ' + @sFind
    
    EXEC(@sSQL)
END
本回答被网友采纳
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式