–hive基本语法10/11–
–dbeaver链接hive的办法:如果vscode上面有做端口映射 可以直接使用localhost登录;如果没有做端口映射,需要用主机ip地址登录
–dbeaver链接mysql的办法:先在vscode上面有做端口映射 再根据映射的端口登录即可
show databases; --只会删除元数据(mysql的数据)

–删除数据库 加上cascade关键字会做级联删除,把数据库以及数据库下的所有表跟内容都删除掉
–而且 会同时mysql上的元数据跟hdfs上的文件内容;
drop database test_db cascade; --mysql上的元数据跟hdfs上的test_db同时删除

create database if not exists test_db;
use test_db ;

–常见数据类型
–数值类型: 整数: int bigint 浮点数: double
–字符类型:string 可变
–时间类型:timestamp
–复合数据类型(hive特有):
–struct key固定、value可变 struct<key1:string, key2:string>
–map key跟value都不固定 mapstring:int
–array array

create table test_tb(
 id int,
 name string
 )
 row format delimited --指定行分隔符 默认回车键
 fields terminated by ‘,’ --指定列分隔符 指定为逗号
 ;select * from test_tb ;
 –查看表结构
 desc test_tb;
 desc formatted test_tb ; --常用 看以看到元数据与hdfs上数据的对应关系
 show create table test_json2 ; --也可看见对应关系–上传数据
 –hive上传:
 –local 关键字表示从本地Linux上传 上传后 本地文件依然存在
 –load data local inpath ‘数据路径’ into table 表名;
 –若无local关键字 就代表从hdfs上移动数据到表里面 移动后源数据消失
 –load data inpath ‘数据路径’ into table 表名;
 –下面的命令可以直接在hive运行 没有hdfs
 –dfs -put ‘本地路径’ ‘hdfs表的路径 /…/库/表/文件名’
 –本地上传(linux)
 –hdfs dfs -put ‘本地路径’ ‘hdfs表的路径 /…/库/表/文件名’load data local inpath ‘/home/bi008/data.txt’ into table test_tb ;
 load data inpath ‘/data.txt’ into table test_tb; --hdfs根目录下的data.txt文件被移动
 dfs -put /home/bi008/data.txt /usr/local/hive_dw/test_db.db/test_tb/data3.txt;–本地上传
 –hdfs dfs -put /home/bi008/data.txt /usr/local/hive_dw/test_db.db/test_tb/data4.txt
 SELECT * from test_tb ;
 –TRUNCATE table test_tb ;
 –查看
 dfs -cat /usr/local/hive_dw/test_db.db/test_tb/data4.txt–自定义表 存储json类型数据
 /*
 {
 “name”: “tom”,
 “friends”: [“jerry” , “lily”],
 “children”: { “tom1”: 5 , “tom2”: 3,“tom3” :6},# map key 和values都是不固定
 “address”: { “street”: “宝安大道” , “city”: “深圳”} # struct key 是固定的 value是不固定
 }


需要将上述的结构的数据转化成 hive能识别的结构化的数据,集合数据按照下划线隔开,map数据按照:隔开,将数据保存为test.txt

/
 /
 tom,jerry_lily,tom1:5_tom2:3,宝安大道_深圳
 ltom,jerry_lily,tom1:3_tom2:2,baoan_sz
 */
 show tables;create table if not exists test_json(
 name string,
 friends array,
 children map<string, string>,
 address struct<street:string, city:string>
 )
 row format delimited
 fields terminated by ‘,’
 collection items terminated by ‘_’ --数组元素分隔符
 map keys terminated by ‘:’ --map中key跟value之间的分隔符
 ;–上传数据
 load data local inpath ‘/home/bi008/json_data.txt’ into table test_json;
 truncate table test_json ;
 SELECT * from test_json ;–查询复合类型数据
 SELECT
 t.name
 , t.friends
 , t.friends[0] --array数组类型通过[下标]方式获取 可通过size来获取长度
 , size(t.friends)
 , t.children[‘tom1’] --map类型通过[key]方式获取 可通过size获取长度
 , t.children[‘alix1’]
 , size(t.children)
 , t.address.street --struct类型通过.方式获取元素
 , t.address.city
 from test_json t;–另外一种方式 把整个json对象当成一整条记录导入 再通过json解析函数来查询数据
 – 数据文件
 /*
 { “name”: “tom”, “friends”: [“jerry” , “lily”],“children”: { “tom1”: 5 , “tom2”: 3 },“address”: { “street”: “宝安大道” , “city”: “深圳”}}
 { “name”: “tom2”, “friends”: [“jerry” , “lily”],“children”: { “tom1”: 5 , “tom2”: 3 },“address”: { “street”: “宝安大道” , “city”: “深圳”}}
 */
 create table if not exists test_json2(
 str string
 )
 row format delimited ; --不用定义列分隔符
 –上传数据
 load data local inpath ‘/home/bi008/json_data2.txt’ into table test_json2 ;
 SELECT * from test_json2 ;
 –drop table test_json2
 –通过get_json_object(字段,‘.name’) –.friends’)
 ,GET_JSON_OBJECT(str, ‘.children’) children
 ,GET_JSON_OBJECT(str, ‘.children.alix1’)
 ,GET_JSON_OBJECT(str, ‘.address.street’)
 ,GET_JSON_OBJECT(str, ‘$.address.city’)
 from test_json2) t;–内部表(管理表)跟外部表
 –内部表(管理表)
 –默认的建表语句创建的是内部表,当表被删除时,mysql上的元数据以及hdfs的文件也会被删除
 –创建表时如果没有指定路径,默认会在hdfs上面新建一个名字跟表名一样的文件夹
 desc formatted test_json ; --通过里面的table type 查看表的类型 MANAGED_TABLE 表示为内部表
 –外部表
 –可通过external关键字来创建外部表,当外部表被删除时,只是删除了mysql上的元数据,hdfs的文件并不会被删除
 –当重新构建一个数据结构一样的表时,依然可以查询到hdfs上对应的文件数据,工作中使用的是外部表
 create external table if not exists wb_table(
 id int,
 name string
 )
 row format delimited
 fields terminated by ‘,’
 stored as textfile --声明存储类型:分为行存储(textfile\sequencefile),跟列存储(RCfile\ORCfile),默认为行存储
 location ‘/data/test/wb_test’; --指定存储路径desc formatted wb_table ; --通过里面的table type 查看表的类型EXTERNAL_TABLE表示为外部表
 –创建层级路径
 –dfs -mkdir -p /data/test;load data local inpath ‘/home/bi008/wb_data.txt’ into table wb_table;
 SELECT * from wb_table ;drop table wb_table ; – 只是元数据被删除 hdfs 文件数据依然存在
SELECT * from test_tb ;
 desc formatted test_tb ; --MANAGED_TABLE 内部表drop table test_tb ; --mysql中的元数据以及hdfs上的数据文件一同被删除
–内部表跟外部表的相互转换 关键字要大写
 –tblproperties(‘EXTERNAL’=‘TRUE’) 内部表–>外部表
 –tblproperties(‘EXTERNAL’=‘FALSE’) 外部表–>内部表alter table test_json set tblproperties (‘EXTERNAL’=‘TRUE’);
 desc formatted test_json ; --转化为外部表alter table wb_table set tblproperties (‘EXTERNAL’=‘FALSE’);
 desc formatted wb_table ; --转化为内部表–表复制 默认会在hdfs默认路径下创建一个跟表名字一样的文件夹
 create table test_table as select * from wb_table ;desc formatted test_table ;
 select * from test_table ;
 –只复制表结构 默认也是会在hdfs默认路径下创建一个跟表名字一样的文件夹
 create table test_table2 like wb_table ; --效率更高
 –或者
 create table test_table3 as select * from wb_table where 1=2;–都是内部表 会同时删除文件数据
 drop table test_table ;
 drop table test_table2 ;
 drop table test_table3 ;–hive中null跟空串的处理
 –在hive中,null在底层数据保存为\N,而空串保存为’’
 –使用is null时,无法查询到空串,需要将空串转化为null统一起来
 –就能够使用is null一起过滤出来
 create table if not exists nl_table(
 id int,
 name string,
 age int,
 score double
 )
 row format delimited
 fields terminated by ‘,’
 stored as textfile;–插入数据
 insert into nl_table values
 (null,null,10,98),
 (2,‘’,10,89),
 (3,‘kk’,12,null);drop table nl_table ;
–查询数据
 SELECT * from nl_table where name is null;
 –将空串转换为null
 alter table nl_table set serdeproperties(‘serialization.null.format’=‘’);
 –查看对null的处理方式
 desc formatted nl_table ; --serialization.null.format
 –清空数据后再重更新插入数据即可
 TRUNCATE table nl_table ;insert into nl_table values
 (null,null,10,98),
 (2,‘’,10,89),
 (3,‘kk’,12,null);SELECT * from nl_table where name is null;
–hive表分区 单分区 多分区
 –分区表实际上就是对应一个 HDFS 文件系统上的独立的文件夹,该文件夹下是该分区所有的数据文件。
 –Hive 中的分区就是分目录,把一个大的数据集根据业务需要分割成小的数据集。
 –在查询时通过 WHERE 子句中的表达式选择查询所需要的指定的分区,这样的查询效率会提高很多
 –单分区表(基本分区)
 –静态分区
 –创建部门表指定按照月份分区 注意:分区字段不能出现在建表字段里面
 create table if not exists fq_table(
 id int,
 name string
 )
 partitioned by(months string) --指定分区字段为月份
 row format delimited
 fields terminated by ‘,’;–上传数据
 load data local inpath ‘/home/bi008/my_hive/fq_data.txt’ into table fq_table partition (mnotallow=‘202210’);
 SELECT * from fq_table ;
 load data local inpath ‘/home/bi008/my_hive/fq_data.txt’ into table fq_table partition (mnotallow=‘202211’);
 SELECT * from fq_table ;–查看分区
 show partitions fq_table;
 –按照分区来查询数据
 SELECT * from default.fq_table where mnotallow=‘202210’;
 SELECT * from fq_table where mnotallow=‘202211’;–增加分区 增加多个用空格分开
 alter table fq_table add partition(mnotallow=‘202209’) partition(mnotallow=‘202212’);
 show partitions fq_table ;
 –删除分区 删除多个分区需要用逗号分开
 alter table fq_table drop partition(mnotallow=‘202209’), partition(mnotallow=‘202212’);
 show partitions fq_table ;desc formatted fq_table ;
drop table fq_table ;
–多分区 创建部门表指定按照年 月 日分区
 create table if not exists fq_table(
 id int,
 name string
 )
 partitioned by(years string, months string, days string) --指定分区字段为月份
 row format delimited
 fields terminated by ‘,’;–使用 load data 方式传入数据 自己建立得文件件可以自动当做分区
 –如果使用 dfs -put 上传数据到自己建立得文件夹中,该文件夹不会自动当做分区,除非再使用添加分区add partition的方式添加分区
 load data local inpath ‘/home/bi008/my_hive/fq_data.txt’ into table fq_table partition(years=‘2020’, mnotallow=‘202006’, days=‘20200615’);load data local inpath ‘/home/bi008/my_hive/fq_data.txt’ into table fq_table partition(years=‘2021’, mnotallow=‘202106’, days=‘20210615’);
SELECT * from fq_table
 where years = ‘2020’
 and months = ‘202006’;show partitions fq_table ;
–动态分区
 –对分区表 Insert 数据时候,数据库自动会根据分区字段的值,将数据插入到相应的分区中
 –hive开启动态分区需要先设置参数
 –(1)开启动态分区功能(默认 true,开启)
 – hive.exec.dynamic.partitinotallow=true
 –(2)设置为非严格模式(动态分区的模式,默认 strict,表示必须指定至少一个分区为静态分区,nonstrict 模式表示允许所有的分区字段都可以使用动态分区。)
 – hive.exec.dynamic.partition.mode=nonstrict
 –(3)在所有执行 MR 的节点上,最大一共可以创建多少个动态分区。
 – hive.exec.max.dynamic.partitinotallow=1000
 –(4)在每个执行 MR 的节点上,最大可以创建多少个动态分区。该参数需要根据实际的数据来设定。比如:源数据中包含了一年的数据,即 day 字段有 365 个值,那么该参数就需要设置成大于 365,如果使用默认值 100,则会报错。
 – hive.exec.max.dynamic.partitions.pernode=100
 –(5)整个MR Job 中,最大可以创建多少个HDFS 文件。
 – hive.exec.max.created.files=100000
 –(6)当有空分区生成时,是否抛出异常。一般不需要设置。
 – hive.error.on.empty.partitinotallow=false
 –注意 参数的设置只是针对当前进程有效 一旦本次进程结束 设置失效
 set hive.exec.dynamic.partition = true;
 set hive.exec.dynamic.partition.mode = nonstrict;
 set hive.exec.max.dynamic.partitions = 1000;
 set hive.exec.max.dynamic.partitions.pernode = 100;
 set hive.exec.max.created.files = 100000;
 set hive.error.on.empty.partition = false;–创建动态分区表将emp表的数据按照部门id分区存放
 create table if not exists dtfq_table(
 id int,
 name string,
 dept string
 )
 partitioned by(dept_id string)
 row format delimited
 fields terminated by ‘,’;–往动态分区表插入的数据必须事先存在另外一个表里面
 –所以先建一个存放数据的表
 drop table emp;
 create table if not exists emp(
 id int,
 name string,
 dept string,
 dept_id string
 )
 row format delimited
 fields terminated by ‘,’;load data local inpath ‘/home/bi008/my_hive/dtfq_data.txt’ into table emp;
 SELECT * from emp;–往动态分区表插入数据 insert overwrite table partition select * from table;
 insert overwrite table dtfq_table partition (dept_id)
 select id, name, dept, dept_id from emp;SELECT * from dtfq_table ;
 –会自动按照部门分好区
 show partitions dtfq_table ;
 desc formatted dtfq_table ;

–分区与分桶的区别
–分区:Hive在查询数据的时候,一般会扫描整个表的数据,会消耗很多不必要的时间。
–有些时候,我们只需要关心一部分数据,比如WHERE子句的查询条件,那这时候这种全表扫描的方式是很影响性能的。
–从而引入了分区的概念。分区就是对数据进行分类,这样在查询的时候,就可以只是针对分区查询,从而不必全表扫描。
–一个目录对应一个分区

–分桶:并非所有的数据集都可形成合理的分区,特别之前所提到过的要确定合适的划分大小的疑虑。
–对于每一个表或者分区,可以进一步细分成桶,桶是对数据进行更细粒度的划分。
–Hive默认采用对某一列的每个数据进行hash(哈希),使用hashcode对 桶的个数求余,确定该条记录放入哪个桶中。
–分桶实际上和 MapReduce中的分区是一样的。分桶数和reduce数对应。
–一个文件对应一个分桶

–hive数据分桶
–表分区的对象是存储路径,而数据分桶的对象是文件数据
–原理是对源数据经过哈希算法得到的哈希值对分桶数取余数,余数相同的数据将被分到一个桶
–每一桶的数据量并一定相同
–分桶的作用 将大表拆分为小表 提高连表效率
–数据分桶也要事先设置参数 参数也只是对当前进程有效

set hive.enforce.bucketing = true;
set mapreduce.job.reduces = 4;

–构建一张分桶表 按照工资分桶

drop table ft_table ;
 create table if not exists ft_table(
 id int,
 name string,
 sal double
 )
 clustered by (sal) into 4 buckets --按照sal分4个桶
 row format delimited
 fields terminated by ‘,’;desc formatted ft_table ;
 –与分区一样 通过load方式上传的数据会自动分桶 而通过dfs -put 方式上传的数据不会被分桶
 load data local inpath ‘/home/bi008/my_hive/ft_data.txt’ into table ft_table ;SELECT * from ft_table
–通过insert方式插入数据 先构建一张表
 create table if not exists test_ft_table(
 id int,
 name string,
 sal double
 )
 row format delimited
 fields terminated by ‘,’;SELECT * from test_ft_table ;
 TRUNCATE table test_ft_table ;
 load data local inpath ‘/home/bi008/my_hive/test_ft_data.txt’ into table test_ft_table ;
 –从测试表查询数据然后插入分桶表 注意顺序要与分桶表字段顺序一致
 insert into table ft_table
 select id,name,sal --顺序不能乱 要与ft_table建表时的顺序一致
 from test_ft_table ;select * from ft_table ;
–分桶的抽样查询 tablesample
 –TABLESAMPLE(BUCKET x OUT OF y)
 select * from ft_table tablesample (bucket 1 out of 4 on sal);–hive排序
 –hive中一共存在四种排序方式:order by 、sort by 、distribute by 、cluster by.
 –order by :全排序
 –order by 是最常用的一种排序,全局排序,所有的数据会在一个reducer上面进行排序,所以一般使用这个函数进行排序的时候速度较慢–sort by 是在进去reducer之前进行的排序,并不是全局排序。只能保证在进入同一个reducer里面的数据是有序的。有别于order by ,sort by可以指定reducer的个数,然后再对reducer里面的数据再排序,也可以得到全局的排序结果。
–distribute by 一般是配合sort by 使用的。distribute 是控制在map端的数据拆分到那个reducer去进行聚合。在某些情况下,需要控制某行记录大某个reducer上。
 –小文件很多 map文件大小不均 文件内容很大 reduce接受的文件大小不均–cluster除了具备distribute by的功能之外还具有sort by的功能
 –当 distribute by 和 sort by 字段相同时 可以使用cluster by 替代
 –局限性就是:只能进行倒序排序–创建一个分桶表 并且创建时排序
 create table if not exists pxft_table(
 id int,
 name string,
 sal double,
 dept_id int,
 dept string
 )
 clustered by (id)
 sorted by (id desc) --排序
 into 4 buckets
 row format delimited
 fields terminated by ‘,’;load data local inpath ‘/home/bi008/my_hive/pxft_data.txt’ into table pxft_table ;
 SELECT * from pxft_table–cluster 单独使用 不能跟distribute 获取 sort 一起使用
 select * from pxft_table cluster by (id);
 –distribute 要结合 sort 一起使用
 –里面字段都是id 结构等同于 cluster
 SELECT * from pxft_table distribute by (id) sort by (id);select * from pxft_table distribute by (id) sort by (sal);
select * from pxft_table distribute by (dept) sort by (sal asc);
select * from pxft_table distribute by (dept_id) sort by (sal desc);
–数据的导入导出
 –数据的导入
 –load data [local] inpath ‘路径’ into table | overwrite 表名 [partition()];
 –(1)load data:表示加载数据
 –(2)local:表示从本地加载数据到 hive 表;否则从HDFS 加载数据到 hive 表
 –(3)inpath:表示加载数据的路径
 –(4)overwrite:表示覆盖表中已有数据,否则表示追加
 –(5)into table:表示加载到哪张表
 –(6)表名字:表示具体的表
 –(7)partition:表示上传到指定分区–通过查询语句向表中插入数据
 select * from fq_table;insert into table fq_table partition (months=‘202210’)
 values (6,‘dd’);insert into table fq_table partition (months=‘202210’)
 select id,name from fq_table where months = ‘202211’;–多模式插入 提升效率
 from fq_table
 insert overwrite table fq_table partition (months=‘202101’)
 select id ,name where months=‘202210’
 insert overwrite table fq_table partition (months=‘202102’)
 select id, name where months=‘202211’;–# 创建表指定路径
 –create table student(id int, name string) partitioned by (month string) row format delimited fields terminated by ‘,’
 –location ‘/user/hive/warehouse/student5’;–# 上传数据
 –dfs -put /opt/module/datas/student.txt /user/hive/warehouse/student5;–数据导出
 – 1.将查询的结果导出到本地 特别注意路径一定要直接的路径,要不就会覆盖内容
 –导出的内容格式默认为hdfs默认的存储格式
 insert overwrite local directory ‘/home/bi008/my_hive/dc_data’
 SELECT * from fq_table ;–可以指定导出的数据格式
 insert overwrite local
 directory ‘/home/bi008/my_hive/dc_data’
 row format delimited fields terminated by ‘,’ --指定为逗号分隔符
 SELECT * from fq_table ;–虚拟表
 –hive 3.X版本自带虚拟表可以直接 select 1 运行
 –或者需要先创建虚拟表
 create table dual(str string);
 – 插入数据 如果没有数据没办法做测试
 insert into dual values(‘x’);– 测试是否可以使用虚拟表 测试函数
 SELECT
 123 num
 , ‘asd’ str
 , 1+2 sums
 , MOD(10,3) mod_yu
 from dual–hive函数
 – nvl 函数
 – 基本语法 NVL(表达式 1,表达式 2) 如果表达式 1 为空值,NVL 返回值为表达式 2 的值,否则返回表达式 1 的值。
 – 该函数的目的是把一个空值(null)转换成一个实际的值。
 – 其表达式的值可以是数字型、 字符型和日期型。但是表达式 1 和表达式 2 的数据类型必须为同一个类型。
 select nvl(null,0), nvl(1,0);–日期
 SELECT
 unix_timestamp() sjz --返回linux时间戳 注意是少8小时的
 , from_unixtime(unix_timestamp()+86060) --加上86060才能返回系统当前时间
 , date_format(‘2022-10-13 12:56:01’, ‘yyyy’)
 , date_format(‘2022-10-13 12:56:01’, ‘MM-dd ss’)
 , year(‘2022-10-13 12:56:01’); --字符串如果符合日期格式 会自动当成日期处理 不需要to_dateselect
 year(‘2022-10-13 12:56:01’)
 – , month(‘2022-10-13 12:56:01’)
 – , hour(‘2022-10-13 12:56:01’)
 – , WEEKOFYEAR(‘2022-10-13 12:56:01’) --返回一年中的第几周
 – , datediff(‘2012-06-08’,‘2012-05-09’) --返回两个日期之间的天数差
 – , date_add(‘2022-10-13’,1)
 , date_add(‘2022-10-13’,-2); --日期加减多少天的日期– next_day 函数
 – 取当前天的下一个周一日期
 select
 next_day(‘2022-10-13’,‘MO’)
 –说明:星期一到星期日的英文(Monday,Tuesday、Wednesday、Thursday、Friday、Saturday、Sunday)–获取当前周的周一日期
 select
 date_add(next_day(‘2022-10-13’,‘MO’),-7);
 –获取当月份最后一天的日期
 select last_day(‘2022-10-13’);–字符函数
 select
 CONCAT(‘qq’, ‘ww’, ‘ee’)
 , CONCAT(‘qq’, ‘ww’, null) --结果为null
 , concat_ws(‘-’,‘qq’,‘xx’,‘mm’) --按照指定字符拼接
 , concat_ws(‘-’,‘qq’,null,‘mm’) --会自动忽略null
 , split(‘aa-ss-dd’,‘-’)[0] --切分后会产生一个集合–collect_set函数
 –把同一分组的不同行的数据聚合成一个集合
 select
 t.dept
 , collect_set(t.id)
 , collect_set(t.id)[0] --可通过下标取出来
 , sum(t.sal)
 from pxft_table t
 group by t.dept– STR_TO_MAP 函数
 –语法描述 STR_TO_MAP(VARCHAR text, VARCHAR listDelimiter, VARCHAR keyValueDelimiter)
 – 功能描述 使用 listDelimiter 将 text 分隔成 K-V 对,然后使用 keyValueDelimiter 分隔每个 K-V 对, 组装成 MAP 返回。
 –默认 listDelimiter 为(,),keyValueDelimiter 为(=)。select
 str_to_map(‘name=kk,age=12,sex=m’,‘,’,‘=’)–hive表连接以及优化
–正则表达式
 –匹配简单字符//
 –字符集合[]
 –量词{n,m}、?、+、*
 –?匹配0次或1次,优先匹配1次,相当于{0,1}
 –+匹配1-n次,优先匹配n次,相当于{1,}
 –*匹配0-n次,优先匹配n次,相当于{0,}
 –边界字符 ^在[]外表示匹配开头的意思 $表示匹配结尾的意思
 –选择表达式 正则中用|来表示分组,a|b表示匹配a或者b的意思
 –分组与引用 分组是正则中非常强大的一个功能,可以让上面提到的量词作用于一组字符,而非单个字符,分组的语法是圆括号包裹(xxx)–SELECT
 – REGEXP_EXTRACT(‘aa-bb/dd:dD,123[哈哈}’,‘(^-.*){6}’,0) --分组
 – ,REGEXP_EXTRACT(‘aa-bb/dd-dD-123[哈哈}’,‘([^-])+’,0)
 – ,REGEXP_EXTRACT(‘aa-bb/dd:dD,123[哈哈}’,‘哈{1,3}?’,0)
 – ,REGEXP_EXTRACT(‘aa-bb/dd:dD,123[哈哈}’,‘[\d]’,0)
 – ,REGEXP_EXTRACT(‘aa-bb/dd:dD,123[哈哈}’,‘[abd]+’,0)
 – ,REGEXP_EXTRACT(‘aa-bb/dd:dD,123[哈哈}’,‘[0-9]{1,4}’,0)
 –from test_json ;select ‘aa-ss-dd’
 ,length(‘aa-ss-dd’)
 – ,reverse(‘aa-ss-dd’)
 – ,SUBSTR(‘aa-ss-dd’,1,3)
 – ,SUBSTRING(‘aa-ss-dd’,1,3)
 – ,UPPER(‘aa-ss-dd’)
 – ,ucase(‘aa-ss-dd’)
 ,trim(‘a s-s–sd ‘) --去除字符两边的空格
 ,REGEXP_REPLACE(‘aa-ss-dd’,‘aa|ss’,’’)
 ,REGEXP_EXTRACT(‘aa-ss-dd’,‘[^ss]+’,0)
 from test_json2 ;