给SQL写个自定义函数

545 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第5天,点击查看活动详情

在我们日常开发的时候,大多数都是写代码,或者一些简单的sql语句,可是有时候我们的数据在库表存储后我们总是会接到某些变更,比如某个逻辑调整,我们需要批量修改某个字段的值,如果直接覆盖那自然很简单,直接update即可,

 可是如果我们的字段只是需要修改里面的部分内容呢,咋办,如果固定格式的也许我们可以提取里面的固定内容直接replace即可,update 表名 set 字段 = REPLACE(字段, '要修改的内容' , '修改后的内容'),这个很简单哈 。

可是如果你的字段的值里有变量(好比内容是xx1,xx2,xx3,xx5),那我需要给xx4呀,那下一个可能需要给xx3,那我就需要根据前面的内容决定后面的内容给几,replace已经不好使了, 我们试试自己写个函数看看能不能处理;(答案肯定是可能的,咱们不是DB大牛,所以写写简单的) 

首先我们定义函数名由于我们的是JSON,所以我这块返回个JSON,

create funetion 函数名(参数) RETURNS json 

begin 

定义变量:

 declare dateObj;
 declare xxxKey varchar(50); 
declare jsonLength int; 
declare i int default 0; 
set dateObj = json_extract(params, '$[0].xxx[2].yyy'); 

该句json_extract表示取params里的数据的第三个xxx的value里的key为yyy的value值 

例如:['aa', {"a": [1, 2], "c": "mm"}, [11, 22]],

那么:

 $[0]:aa 
$[1]: {"a": [1, 2], "c": "mm"} 
$[1].a[1, 2] 
$[1].a[0]1 
$[1].c:mm 
$[2][11, 22] 
$[2][0]11 

set jsonLength = JSON_LENGTH(json_extract(params, '$[0].xxx[2].yyy')); 该句是取数组或对象的长度(用例取自官方文档)

mysql> SELECT JSON_LENGTH('[1, 2, {"a": 3}]');
+---------------------------------+
| JSON_LENGTH('[1, 2, {"a": 3}]') |
+---------------------------------+
|                               3 |
+---------------------------------+
mysql> SELECT JSON_LENGTH('{"a": 1, "b": {"c": 30}}');
+-----------------------------------------+
| JSON_LENGTH('{"a": 1, "b": {"c": 30}}') |
+-----------------------------------------+
|                                       2 |
+-----------------------------------------+
mysql> SELECT JSON_LENGTH('{"a": 1, "b": {"c": 30}}', '$.b');
+------------------------------------------------+
| JSON_LENGTH('{"a": 1, "b": {"c": 30}}', '$.b') |
+------------------------------------------------+
|                                              1 |
+------------------------------------------------+

然后循环取出的dateObj内容里的对应key,如果xxxKey = '"目的key"'则进入下一步

while i<jsonLength do
set xxxKey = json_extract(dateObj, concat('$[',i,'].child[0].xxxKey'));
IF xxxKey = '"目的key"' THEN

接着取出该key对应的value值,依然使用json_extract取,这里就不贴代码了,后查看该value的长度,

set xxxContentIndex = JSON_LENGTH(xxxContent)-1;

set xxxm = replace(replace(json_extract(xxxContent, concat('$[',xxxContentIndex,'].key')),'{',''),'}','');

取出该value的最后一个对象的value并进行相应的格式替换,然后判断该value中是否存在目的key,=0表示不存在,那我们定义个变量,里面的动态值是xxxNext,我们给这个变量格式设为JSON;

set xxxNext = cast(replace(xxxm,'"','') as SIGNED)+1;
IF LOCATE('目的key', xxxContent) = 0  THEN
set res = CONVERT(concat('{"目的key":"{',xxxNext,'}","value":"ID","content":""}'), JSON);

然后通过JSON_INSERT将params拼接下返回,最后如下

json_insert(params, concat('$[0].xxx[2].yyy','[',i,'].child[0].mmm[',xxxNext,']'), res);
		END IF;
	END IF;
	set i = i+1;
end while;
return params;
end

里面的key定义的变量可能有误,但具体逻辑是那么回事

最后update直接调用该函数即可