在 case 语句中更新值并设置局部变量

Posted

技术标签:

【中文标题】在 case 语句中更新值并设置局部变量【英文标题】:Update a value and set a local variable in a case statement 【发布时间】:2022-01-12 22:18:39 【问题描述】:

我正在尝试更新数据库中的值,但也想设置一个局部变量VAR_IS_RATE_LIMITED。这样做的原因是因为我不想使用 select 语句并希望在一个语句中执行它。如何设置VAR_IS_RATE_LIMITED?我查看了其他问题,但他们的 CASE 语句没有嵌入到更新语句中。

DELIMITER //
CREATE FUNCTION F_RATE_LIMITED(P_IP varchar(45),
                               P_MAX_RATE int unsigned
                            )
RETURNS INT UNSIGNED
BEGIN

    DECLARE VAR_IS_RATE_LIMITED INT UNSIGNED DEFAULT 0;

    INSERT INTO rate_limit (ip, rate)
        VALUES (P_IP, 1)
    ON DUPLICATE KEY UPDATE 
        rate = 
            CASE
                WHEN (rate + 1) > P_MAX_RATE THEN
                    SET VAR_IS_RATE_LIMITED = 1;
                    rate
                ELSE
                    rate + 1
            END;

    RETURN VAR_IS_RATE_LIMITED;
END; //
DELIMITER ;

【问题讨论】:

很遗憾,你不能这样做,它不能那样工作,你不能在update 语句中设置变量。 @Stu 在不使用 select 语句的情况下,有什么解决方案可以解决我想要做的事情吗?本质上,我想要的是,如果您超过了速率,我希望函数返回 1。 【参考方案1】:

要在数据修改语句期间设置某些内容,它必须是表达式的一部分,而不是语句。据我所知,您不能在表达式中设置存储的函数变量。但是你可以设置一个用户变量:

DELIMITER //
CREATE FUNCTION F_RATE_LIMITED(P_IP varchar(45),
                               P_MAX_RATE int unsigned
                            )
RETURNS INT UNSIGNED
BEGIN

    SET @VAR_IS_RATE_LIMITED = 0;
    INSERT INTO rate_limit (ip, rate)
        VALUES (P_IP, 1)
    ON DUPLICATE KEY UPDATE
        rate =
            CASE
                WHEN (rate + 1) > P_MAX_RATE THEN
                    CASE WHEN @VAR_IS_RATE_LIMITED := 1 THEN rate END
                ELSE
                    rate + 1
            END;

    RETURN @VAR_IS_RATE_LIMITED;
END; //
DELIMITER ;

这里的变量是在 CASE 测试中设置的(您也可以使用 IF 表达式),该测试始终为真,因此始终从 CASE 返回 rate。

【讨论】:

理论上你可以在 INSERT 之后检查 FOUND_ROWS() ;如果插入了一行,它应该是 1,如果更新了一行,它应该是 2,如果达到限制,它应该是 0,所以没有发生任何变化。但我无法让它工作。

以上是关于在 case 语句中更新值并设置局部变量的主要内容,如果未能解决你的问题,请参考以下文章

在CTE sql的select语句中更新局部变量

从子shell返回值并输出到局部变量

在switch中的case语句中声明变量会被提前

动态设置局部变量[重复]

Cloud Firestore 中的每个数据更改都更新了局部变量

如何在jdbc中为事务设置局部变量