[1219]mysql自定义函数split_part、split_last

Mysql创建自定义函数

基本语法

delimiter 自定义符号  -- 如果函数体只有一条语句, begin和end可以省略, 同时delimiter也可以省略
  create function 函数名(形参列表) returns 返回类型  -- 注意是retruns
  begin
    函数体    -- 函数内定义的变量如:set @x = 1; 变量x为全局变量,在函数外面也可以使用
   return返回值
  end
  自定义符号
  delimiter ;

关键字delimiter的使用:
delimiter是mysql分隔符。在mysqlclient中分隔符默认是分号(;)。
假设一次输入的语句较多,而且语句中间有分号,这时须要新指定一个特殊的分隔符。
在前一篇中有设置mysql的触发器时使用样例

mysql> delimiter //
mysql> create trigger upd_check before update on account 
    -> for each row
    -> begin
    -> if new.amount < 0 then
    ->  set new.amount=0;
    -> elseif new.amount > 100 then
    ->  set new.amount = 100;
    -> end if;
    -> end;
    -> //
Query OK, 0 rows affected (0.00 sec)

mysql> delimiter ;

上面就是。先将分隔符设置为 //,
直到遇到下一个 //,才总体运行语句。
运行完后。最后一行, delimiter ; 将mysql的分隔符又一次设置为分号;
假设不改动的话,本次会话中的全部分隔符都以// 为准。

创建函数示例

定义一个相加函数myfun3

-- 自定义函数
delimiter $$
create function myfun3(ia int, ib int) returns int
begin
    return ia + ib;
end
$$
delimiter ;

查看函数

show function status [like 'pattern'];  -- 查看所有自定义函数, 自定义函数只能在本数据库使用。
show create function 函数名;  -- 查看函数创建语句

删除函数

drop function 函数名;

调用函数

select myfun3(2,3); --参数需为对应类型

综合应用

使用全局变量

-- 计算1 ~ 指定数据之间的和

delimiter $$
create function my_sum(x int) returns int
begin
    set @i = 1;
    set @sum = 0;
    while @i <= x do
        set @sum = @sum + @i;
        set @i = @i + 1;
    end while;
    return @sum;
end
$$
delimiter ;

使用局部变量

-- 求1 ~ 指定数之前的和,但5的倍数不加

delimiter $$
create function my_sum2(x int) returns int
begin
    declare i int default 1;
    declare sum int default 0;
    sumwhile:while i <= x do
        if i % 5 = 0 then
            set i = i + 1;
            iterate sumwhile;
        end if;
        set sum = sum + i;
        set i = i + 1;
    end while;
    return sum;
end
$$
delimiter ;

mysql自定义函数应用

  • split_part
CREATE DEFINER=`dba`@`%` FUNCTION `clyydb`.`SPLIT_PART`(
`str` varchar(255) charset utf8mb4 collate utf8mb4_general_ci ,`delim` varchar(12) charset utf8mb4 collate utf8mb4_general_ci ,`pos` int(11) ) RETURNS varchar(255) CHARSET utf8mb4
    SQL SECURITY INVOKER
RETURN replace(SUBSTRING(SUBSTRING_INDEX(str, delim, pos),char_length(SUBSTRING_INDEX(str, delim, pos -1))+1),'-','')

使用说明

select 
	split_part('a-b-c-d','-',1) as f1,
	split_part('a-b-c-d','-',2) as f2,
	split_part('a-b-c-d','-',3) as f3,
	split_part('a-b-c-d','-',4) as f4;

image.png

  • split_last
CREATE DEFINER=`dba`@`%` FUNCTION `clyydb`.`split_last`(
`str` varchar(255) charset utf8mb4 collate utf8mb4_general_ci ,`delim` varchar(1) charset utf8mb4 collate utf8mb4_general_ci ) RETURNS varchar(255) CHARSET utf8mb4
    SQL SECURITY INVOKER
begin 
    declare returnstring varchar(255);
    if char_length(str)=char_length(replace(str,delim,'')) then 
        set returnstring=str;
    else 
        set returnstring=replace(REVERSE(LEFT(REVERSE(str),INSTR(REVERSE(str),delim))),delim,'');
    end if ; 
    return returnstring;
end

使用说明

select 
	split_last('a-b-c-d','-') as f1,
	split_last('a-b-c-','-') as f2;

image.png

  • clean_partitions
CREATE DEFINER=`fanruan_dba`@`%` PROCEDURE `clyydb`.`clean_partitions`(in table_name varchar(128))
BEGIN
    DECLARE start_date VARCHAR(50);
    DECLARE end_date VARCHAR(50);
    DECLARE partition_name VARCHAR(50);

    -- 获取当前日期
    SET @current_date = CURDATE();

    -- 开始日期:INFORMATION_SCHEMA.PARTITIONS 表中最小分区 设置默认值20210101
    -- 结束日期:以当前时间往前三个月

    -- 查询最小分区 作为开始时间
    SET @str_sql=concat('SELECT coalesce(min(substring(partition_name,6,13)),''20210101'') into @tmp_startDate FROM INFORMATION_SCHEMA.PARTITIONS where TABLE_NAME =''', table_name,'''');
     PREPARE stmt FROM @str_sql;
     EXECUTE stmt; 
     DEALLOCATE PREPARE stmt;

    SET start_date = DATE_FORMAT(@tmp_startDate, '%Y-%m-%d');

    SET end_date = DATE_SUB(@current_date, INTERVAL 92 day);
     -- select @str_sql,start_date,end_date,table_name,@current_date;

    SET @partition_name = CONCAT('part_', DATE_FORMAT(start_date, '%Y%m%d'));
    SET @str_sql = '';
    SET @partition_list ='';
     
    WHILE start_date <= end_date DO
        -- 获取当月的最后一天
       SET @month_lastday = LAST_DAY(start_date);
      
      -- 判断分区是否存在
       SET @tmp_sql = concat('SELECT COUNT(1) INTO @partition_count FROM information_schema.PARTITIONS 
                            where TABLE_NAME =''', table_name,''' and PARTITION_NAME =''',@partition_name,'''');
        
       PREPARE stmt FROM @tmp_sql;
       EXECUTE stmt; 
       DEALLOCATE PREPARE stmt;
   
      -- 分区日期不等于当月最后一天并且分区存在
        IF  start_date <> @month_lastday  and @partition_count > 0  then
            SET @partition_list = CONCAT(@partition_list,',', @partition_name);
            
        end IF;
       
        SET start_date = start_date + INTERVAL 1 DAY;
        SET @partition_name = CONCAT('part_', DATE_FORMAT(start_date, '%Y%m%d'));
        
    END WHILE;
   
     -- 删除历史分区操作
    SET @partition_list = substring(@partition_list,2,length(@partition_list));
       IF  @partition_list <> ''  then
            SET @str_sql = CONCAT('ALTER TABLE ',table_name,' DROP PARTITION  ', @partition_list,';');
            PREPARE stmt FROM @str_sql;
            EXECUTE stmt; 
            DEALLOCATE PREPARE stmt;
        end IF;
END

使用说明

call clean_partitions('表名');

例子:
call clean_partitions('ads_report_24_hour_cabin_daily_1d_test');

mysql运行语句时出现 FUNCTION *** does not exist

这个错误通常是因为你在使用一个不存在的函数。可能是因为你没有正确地创建函数,或者你没有正确地调用函数。

以下是一些可能的解决方案:

1. 确认函数是否存在。你可以使用 SHOW FUNCTION STATUS 命令来查看所有已经创建的函数。

2. 确认函数的名称是否正确。如果你在调用函数时拼写错误,那么就会出现这个错误。

3. 确认函数的参数是否正确。如果你在调用函数时传递了错误的参数,那么就会出现这个错误。

4. 确认函数是否在正确的数据库中。如果你在调用函数时没有指定数据库名称,那么就会默认在当前数据库中查找函数。如果函数不在当前数据库中,那么就会出现这个错误。

5. 确认你是否有足够的权限来访问函数。如果你没有足够的权限来访问函数,那么就会出现这个错误。

如果你仍然无法解决这个问题,那么你可以尝试重新创建函数,或者联系数据库管理员来获取帮助。

参考:https://www.itguest.com/post/edfbf2b5.html
https://blog.csdn.net/qq_43581790/article/details/126800065

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

周小董

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值