Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql MariaDB中生成的列定义中的用户定义函数?_Mysql_Json_Mariadb_User Defined Functions_Virtual Column - Fatal编程技术网

Mysql MariaDB中生成的列定义中的用户定义函数?

Mysql MariaDB中生成的列定义中的用户定义函数?,mysql,json,mariadb,user-defined-functions,virtual-column,Mysql,Json,Mariadb,User Defined Functions,Virtual Column,根据文档,MariaDB允许在生成的列定义中使用用户定义的函数 我使用的是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`) ) EN

根据文档,MariaDB允许在生成的列定义中使用用户定义的函数

我使用的是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 ;
创建表'json\u virt`(
`id`int(11)非空自动增量,
`json_arr`longtext COLLATE utf8mb4_unicode_ci非空,
主键(`id`)
)ENGINE=InnoDB默认字符集=utf8mb4 COLLATE=utf8mb4\u unicode\u ci;
插入json_virt SET json_arr='[“a”,“b”];
插入json_virt SET json_arr='[“c”,“d”];
分隔符//
创建或替换函数`test`.`json_introde`(`data`TEXT,`sep`TEXT)
返回文本
字符集utf8mb4
整理utf8mb4\u unicode\u ci
确定性
SQL安全调用程序
开始
声明i INT无符号默认值为0;
声明v_count INT无符号默认JSON_长度(数据);
声明v_current_item BLOB默认为空;
声明v_current_path BLOB默认为NULL;
声明sep_length INT无符号默认字符长度(sep);
声明str文本默认值“”;
当我数的时候
设置v_current_path=CONCAT(“$[”,i“]);
设置v_current_item=JSON_EXTRACT(数据,v_current_路径);
设置v_current_item=JSON_UNQUOTE(v_current_item);
设置str=CONCAT(str、sep、v_当前项目);
集合i:=i+1;
结束时;
设置str=子字符串(str,sep_长度+1);
返回str;
结束//
定界符;
挑选
json_virt.*,
json_内爆(json_virt.json_arr,,')为json_imp
来自json_virt
;
将表'json_virt'添加'json_str'文本为(json_infradex(json_arr,,'))VIRTUAL;
将表'json_virt'添加'json_str1'文本为json_内爆('[“x”,“y”]',','))虚拟;
正如SELECT语句所示,json_introde()函数工作得很好,但是当尝试执行最后两个ALTER TABLE语句时,两个语句都失败了

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

  • 为什么这样不行
  • 对于生成的列定义,UDF的示例是什么
  • 是否可以在生成的列定义中使用多行或更复杂的代码
  • 有没有更好的方法来完成我要做的事情(取一个JSON数组字段,并对其进行内爆,使每个项以逗号分隔为字符串)

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

    而术语UDF被MySQL/MariaDB用于一个完全不同的特性

    说:

    用户定义函数(UDF)是一种使用一个新函数扩展MariaDB的方法,该函数的工作方式类似于本机(内置)MariaDB函数,如ABS()或CONCAT()

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


    请注意,MicrosoftSQLServer使用UDF来实现类似MySQL/MariaDB的存储函数。这可能是混淆的根源。

    第一个例子中有一个打印错误:<代码> JSONY-ByoDeX 。你得到了什么错误?<代码> JSONY-MyODL<代码>是一个存储函数,不是UDF.UDF是用C或C++编写的。在我的例子中,我假设一个“用户定义函数”是用户定义的函数。我真傻!我应该记得这是2020年。谢谢。MySQL以这种方式使用UDF已有几十年了。
    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 ;