创建MySQL函数

时间:2018-01-03 22:33:50

标签: mysql mariadb

我正在尝试编写一个函数来查找在父子树中为其配置分配的值,如果该值为null或为空,则它会为该值查找一个级别。 我在尝试创建函数时遇到语法错误。 这是我到目前为止所拥有的,

DELIMITER //
CREATE FUNCTION `db`.`Configuration`(
    `ColumnName` VARCHAR(128),
    `CID` INT
)
RETURNS VARCHAR(256)
NOT DETERMINISTIC
BEGIN
    DECLARE Config VARCHAR(256) DEFAULT NULL;
    DECLARE Parent INT;

    WHILE (@Config IS NULL OR @Config = "") DO
        SELECT @ColumnName INTO @Config, `ParentID` INTO @Parent FROM `Table` WHERE `ID`=@CID;
    END WHILE;

    RETURN CONCAT(@Config, '::', @Parent);
    END ;
//
DELIMITER ;

当我尝试添加该功能时,我收到以下错误:

1327 - 未声明的变量:ParentID

非常感谢任何帮助!

2 个答案:

答案 0 :(得分:0)

您的功能存在一些问题:

  • 您错误地使用了SELECT...INTO。选择多个值时,您应该只使用INTO一次。例如SELECT a,b into @a,@b FROM...
  • 您正在使用与您的函数参数具有相似名称的用户定义变量,但它们不是同一个东西。在您的代码CID@CID中有所不同。我建议使用标准命名前缀来阐明这一点:例如,对函数参数使用p_,对本地函数变量使用v_。您根本不需要使用用户定义的变量。
  • 由于查询条件永远不会改变,因此WHILE循环必然会导致无限循环。如果它返回NULL或空字符串一次,它将永远返回它们。

这里有一个快速重写来解决上述问题。我会留给您正确实现WHILE循环:

DELIMITER //
CREATE FUNCTION `db`.`Configuration`(
    p_column_name VARCHAR(128),
    p_id INT
)
RETURNS VARCHAR(256)
READS SQL DATA
BEGIN
    DECLARE v_config VARCHAR(256) DEFAULT NULL;
    DECLARE v_parent INT;

    SELECT p_column_name,`ParentID` 
    INTO v_config, v_parent 
    FROM `Table` 
    WHERE `ID`=p_id;

    RETURN CONCAT(v_config, '::', v_parent);
    END ;
//
DELIMITER ;

答案 1 :(得分:0)

您在问题中收到错误消息,因为您有多个into子句,而根据select ... into ...上的mysql手册,您只能有一个。{因此,要删除此特定错误消息,您需要将select语句重写为:

SELECT @ColumnName, `ParentID` INTO @Config, @Parent FROM `Table` WHERE `ID`=@CID;

但是,您的代码还存在一些问题:

  1. varname@varname不引用相同的变量。第一个是函数/存储过程参数或局部变量,而第二个是用户定义的变量。在您的代码中,您必须从变量名称中删除@

  2. 您不能在sql语句中使用变量代替字段名称。您必须使用带有预准备语句的动态sql来实现此目的。请参阅以下有关如何执行此操作的问题:How To have Dynamic SQL in MySQL Stored Procedure

  3. 您不会在while循环中覆盖CID参数。这意味着如果第一次迭代配置将保持为null,那么您将拥有无限循环。您应该更改循环中CID的值。

  4. 我无法保证您的代码中没有其他错误。