MySQL - 创建用户定义函数 (UDF) 时遇到问题

Posted

技术标签:

【中文标题】MySQL - 创建用户定义函数 (UDF) 时遇到问题【英文标题】:MySQL - Trouble with creating user defined function (UDF) 【发布时间】:2011-07-08 17:53:48 【问题描述】:

我正在尝试创建这个函数:

CREATE FUNCTION remove_non_alphanum (prm_strInput varchar(3000))
RETURNS VARCHAR(3000)
DETERMINISTIC

BEGIN

  DECLARE i INT DEFAULT 1;
  DECLARE v_char VARCHAR(1);
  DECLARE v_parseStr VARCHAR(3000) DEFAULT '';

  WHILE (i <= LENGTH(prm_strInput) )  DO
    SET v_char = SUBSTR(prm_strInput,i,1);

    IF v_char REGEXP '^[A-Za-z0-9]$' THEN
      SET v_parseStr = CONCAT(v_parseStr,v_char);  
    END IF;

    SET i = i + 1;
  END WHILE;

  RETURN trim(v_parseStr);
END

但是 mysql 说:

13:52:45 [CREATE - 0 row(s), 0.000 secs] [Error Code: 1064, SQL State: 42000] 您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,以获取正确的语法,以便在第 5 行的 '' 附近使用

我有什么错?语法对我来说是正确的。

【问题讨论】:

注释掉一些东西(在这种情况下从 WHILE 循环中的 IF 开始)并测试以更好地确定问题。 实际上我应该在查询窗口中运行它吗?这个页面似乎暗示我需要先编译一个 UDF dev.mysql.com/doc/refman/5.0/en/adding-functions.html @Greg,如果您用 C 语言编写函数,情况就是如此。您的代码是 SQL。 【参考方案1】:

您必须更改分隔符,以便在函数内使用;

DELIMITER $$

CREATE FUNCTION remove_non_alphanum (prm_strInput varchar(3000))
RETURNS VARCHAR(3000)
DETERMINISTIC
BEGIN
  DECLARE i INT DEFAULT 1;
  DECLARE v_char VARCHAR(1);
  DECLARE v_parseStr VARCHAR(3000) DEFAULT '';
WHILE (i <= LENGTH(prm_strInput) )  DO
  SET v_char = SUBSTR(prm_strInput,i,1);
  IF v_char REGEXP '^[A-Za-z0-9]$' THEN
        SET v_parseStr = CONCAT(v_parseStr,v_char);  
  END IF;
  SET i = i + 1;
END WHILE;
RETURN trim(v_parseStr);
END
$$

DELIMITER ;

在MySQL Command-Line Client(和许多其他SQL 客户端)中,默认分隔符是;。因此,当您键入原始代码时,MySQL 认为第一个命令在找到第一个 ; 的位置结束(在第 5 行,如错误消息所述),因此您会收到错误,因为这不是有效的 SQL:

CREATE FUNCTION remove_non_alphanum (prm_strInput varchar(3000))
RETURNS VARCHAR(3000)
DETERMINISTIC
BEGIN
  DECLARE i INT DEFAULT 1;

如果您将分隔符更改为其他任何内容,MySQL 会识别完整的命令(从 CREATE FUNCTIONEND 并运行它。瞧!您的函数已创建。最后,当您运行函数时,代码运行正常因为函数体是由几个使用默认分隔符的语句组成的。

【讨论】:

我不明白为什么需要这样做 嗯,现在我收到此错误:14:20:15 [DELIMITER - 0 row(s), 0.000 secs] [Error Code: 1064, SQL State: 42000] 您的 SQL 中有错误句法;检查与您的 MySQL 服务器版本相对应的手册,以获取在 'DELIMITER $$ 附近使用的正确语法 @Greg:我只能说它在我编写它时对我有用(MySQL 5.0)。你用什么来运行代码?该手册指出,DELIMITER 是 mysql 命令行客户端的命令。我正在使用 HeidiSQL 并按预期工作。 感谢您的解释。现在这完全有道理。我想知道它是否因为数据库可视化问题而没有运行?【参考方案2】:

我找到了答案here。

我发现这是一些奇怪的 DB Visualizer 问题。

将完整的块包含在“--/”和“/”中对我有用:

--/
CREATE FUNCTION remove_non_alphanum (prm_strInput varchar(3000))
RETURNS VARCHAR(3000)
DETERMINISTIC
BEGIN
  DECLARE i INT DEFAULT 1;
  DECLARE v_char VARCHAR(1);
  DECLARE v_parseStr VARCHAR(3000) DEFAULT '';
WHILE (i <= LENGTH(prm_strInput) )  DO
  SET v_char = SUBSTR(prm_strInput,i,1);
  IF v_char REGEXP '^[A-Za-z0-9]$' THEN
        SET v_parseStr = CONCAT(v_parseStr,v_char);  
  END IF;
  SET i = i + 1;
END WHILE;
RETURN trim(v_parseStr);
END
/

【讨论】:

【参考方案3】:

替代

--/
CREATE FUNCTION ... 
/ 

是:

@delimiter $$;
CREATE FUNCTION ...
@delimiter ;$$

更多信息:http://www.dbvis.com/doc/main/doc/ug/sqlCommander/sqlCommander.html#mozTocId437790

【讨论】:

以上是关于MySQL - 创建用户定义函数 (UDF) 时遇到问题的主要内容,如果未能解决你的问题,请参考以下文章

第三方组件提权-Mysql UDF提权

每日一问-什么是Mysql数据库的UDF提权?

Databricks - 创建永久用户定义函数 (UDF)

PySpark 用户定义函数 (UDF) 创建新列

MySQL UDF 提权

MySQL UDF提权执行系统命令