1

根据文档,MariaDB 允许在生成的列定义中使用用户定义的函数https://mariadb.com/kb/en/generated-columns/

User-defined functions (UDFs) are supported in expressions for generated columns. However, MariaDB can't check whether a UDF is deterministic, so it is up to the user to be sure that they do not use non-deterministic UDFs with VIRTUAL generated columns. 

我正在使用 MariaDB 10.3.20,并且我创建了一个确定性函数,但是在尝试创建该字段时,它失败了。这是一些示例代码。

CREATE TABLE `json_virt` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `json_arr` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
    PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ;

INSERT INTO json_virt SET json_arr = '["a","b"]' ;
INSERT INTO json_virt SET json_arr = '["c","d"]' ;

DELIMITER //
CREATE OR REPLACE FUNCTION `test`.`json_implode`(`data` TEXT, `sep` TEXT) 
RETURNS text 
CHARSET utf8mb4 
COLLATE utf8mb4_unicode_ci
DETERMINISTIC
SQL SECURITY INVOKER
BEGIN

    DECLARE i INT UNSIGNED DEFAULT 0 ;
    DECLARE v_count INT UNSIGNED DEFAULT JSON_LENGTH(data) ;
    DECLARE v_current_item BLOB DEFAULT NULL ;
    DECLARE v_current_path BLOB DEFAULT NULL ;
    
    DECLARE sep_length INT UNSIGNED DEFAULT CHAR_LENGTH(sep) ;
    
    DECLARE str TEXT DEFAULT '' ;
    
    WHILE i < v_count DO
        SET v_current_path =  CONCAT('$[', i, ']') ;
        
        SET v_current_item = JSON_EXTRACT(data, v_current_path) ;
        SET v_current_item = JSON_UNQUOTE(v_current_item) ;
        
        SET str = CONCAT(str, sep, v_current_item) ;
        
        SET i := i + 1;
    END WHILE;
    
    SET str = SUBSTRING(str, sep_length+1) ;
    
    RETURN str ;
    
END //
DELIMITER ;

SELECT 
json_virt.*,
json_implode(json_virt.json_arr, ', ') AS json_imp
FROM json_virt
;

ALTER TABLE `json_virt` ADD `json_str` TEXT AS (json_implodex(json_arr, ', ')) VIRTUAL ;

ALTER TABLE `json_virt` ADD `json_str1` TEXT AS json_implode('["x","y"]', ', ') VIRTUAL ;

从 SELECT 语句可以看出,json_implode() 函数运行良好,但是在尝试执行最后两个 ALTER TABLE 语句时,都失败了。

我从几个不同的角度对此感兴趣:

  1. 为什么这不起作用?
  2. 适用于生成的列定义的 UDF 示例是什么?
  3. 是否可以在生成的列定义中使用多行或更复杂的代码?
  4. 有没有更好的方法来完成我正在尝试做的事情(获取一个 JSON 数组的字段并将其内爆,以便每个项目都用逗号分隔为字符串)?
4

1 回答 1

2

我看到很多开发人员在使用“UDF”时,他们的意思是 MySQL/MariaDB 所谓的存储函数。也就是说,用基于 ANSI SQL 的语言编写并动态部署在正在运行的 MySQL 服务器上的例程。

而 MySQL/MariaDB 使用 UDF 一词来表示完全不同的功能。

https://mariadb.com/kb/en/create-function-udf/说:

用户定义函数 (UDF) 是一种使用新函数扩展 MariaDB 的方法,该函数的工作原理类似于原生(内置)MariaDB 函数,例如 ABS() 或 CONCAT()。

UDF 需要用 C、C++ 或其他使用 C 调用约定的语言编写,MariaDB 需要已经动态编译,并且您的操作系统必须支持动态加载。

请注意,Microsoft SQL Server 将 UDF 用于更像 MySQL/MariaDB 的存储函数的东西。这可能是混乱的根源。

于 2020-10-01T23:55:21.847 回答