MySQL 用户定义函数 returns 在 SELECT 语句中使用时的值不正确

MySQL user-defined function returns incorrect value when used in a SELECT statement

我在 MySQL 中调用用户定义的函数时遇到问题。计算很简单,就是抓不住哪里出错,为什么出错。事情是这样的。

所以我创建了这个函数:

DELIMITER //
CREATE FUNCTION fn_computeLoanAmortization (_empId INT, _typeId INT)
RETURNS DECIMAL(17, 2) 

BEGIN
    SET @loanDeduction = 0.00;

    SELECT TotalAmount, PeriodicDeduction, TotalInstallments, DeductionFlag
    INTO @totalAmount, @periodicDeduction, @totalInstallments, @deductionFlag
    FROM loans_table
    WHERE TypeId = _typeId AND EmpId = _empId;

    IF (@deductionFlag = 1) THEN
        SET @remaining = @totalAmount - @totalInstallments;

        IF(@remaining < @periodicDeduction) THEN
            SET @loanDeduction = @remaining;
        ELSE
            SET @loanDeduction = @periodicDeduction;
        END IF;
    END IF;

    RETURN @loanDeduction;
END;//
DELIMITER ;

如果我这样调用它,它工作正常:

SELECT fn_computeLoanAmortization(3, 4)

但是如果我在 SELECT 语句中调用它,结果就会出错:

SELECT Id, fn_computeLoanAmortization(Id, 4) AS Amort FROM emp_table

loans_table 中只有一个条目,上面的语句应该只会导致一行在 Amort[=45= 中具有值] 列,但有许多随机行与具有匹配条目的行具有相同的 Amort 值,情况不应该如此。

有没有人遇到过这种奇怪的困境?或者我可能做错了什么。请赐教。

非常感谢。

编辑: 错误的,我的意思是这样的:

loans_table has one record
EmpId = 1
TypeId = 2
PeriodicDeduction = 100
TotalAmount = 1000
TotalInstallments = 200
DeductionFlag = 1

emp_table has several rows 
EmpId = 1
Name = Paolo

EmpId = 2
Name = Nikko

...

EmpId = 5
Name = Ariel

当我查询以下语句时,我得到了正确的值:

SELECT fn_computeLoanAmortization(1, 2)

SELECT Id, fn_computeLoanAmortization(Id, 2) AS Amort FROM emp_table WHERE EmpId = 1

但是当我查询这条语句时,我得到了不正确的值:

SELECT Id, fn_computeLoanAmortization(Id, 2) AS Amort FROM emp_table

结果集将是:

EmpId    |    Amort
--------------------
1        |    100
2        |    100 (this should be 0, but the query returns 100)
3        |    100 (same error here)
...
5        |    100 (same error here up to the last record)

在您的函数中,您用来从 loans_table table 检索值的变量不是函数的局部变量,而是会话变量。当函数内的 select 没有找到任何行时,这些变量仍然具有与上次执行函数相同的值。

改用真正的局部变量。为此,请使用不带@ 的变量名称作为前缀,并在函数开头声明变量。有关详细信息,请参阅 this answer

我怀疑问题是 INTO 中的变量在没有匹配行时没有重新设置。

只需在 之前设置它们 INTO:

BEGIN
    SET @loanDeduction = 0.00;
    SET @totalAmount = 0;
    SET @periodicDeduction = 0;
    SET @totalInstallments = 0;
    SET @deductionFlag = 0;

    SELECT TotalAmount, PeriodicDeduction, TotalInstallments, DeductionFlag
    . . . 

您可能只想将它们设置为 NULL

或者,将您的逻辑切换为使用局部变量:

    SET v_loanDeduction = 0.00;
    SET v_totalAmount = 0;
    SET v_periodicDeduction = 0;
    SET v_totalInstallments = 0;
    SET v_deductionFlag = 0;

以此类推