Search code examples
phpmysqlvariablestemporary

MySQL temporary variable does not work when executed from PHP script


When executing the following query in MySQL the rows are updated correctly.

UPDATE market SET price = 
CASE 
WHEN 
    @order_price:=(
        @market_price:=(IF(
            market_id = 0, 
            (SELECT value FROM fiat WHERE id = 6), 
            (SELECT value FROM fiat WHERE id = 5)
        ) 
        + 
        (
            (order_percentage_dynamic/100) * @market_price
        ))
    ) < IFNULL(exchange_rate_max, 999999999) AND @market_price > IFNULL(exchange_rate_min, -999999999)
THEN @market_price 
WHEN @order_price > exchange_rate_max AND exchange_rate_max IS NOT NULL THEN exchange_rate_max
WHEN @order_price < exchange_rate_min AND exchange_rate_min IS NOT NULL THEN exchange_rate_min 
END 
WHERE bdynamicorder = true;

Executing that same query in a PHP script updates all rows but with NULL value.

if ($update_stmt = $mysqli->prepare($query)) {

    $update_stmt->execute();

}

Any ideas?

Thanks!


Solution

  • I'm pretty sure that the problem is the lack of initialization of the variables. Consider this expression:

    @market_price := (IF(market_id = 0, 
                         (SELECT value FROM fiat WHERE id = 6), 
                         (SELECT value FROM fiat WHERE id = 5)
                        ) + 
                        (order_percentage_dynamic/100) * @market_price
                     )
    

    If @market_price has not been set, then this will return NULL -- when either argument to an arithmetic operator is NULL, the result is NULL.

    One solution uses additional logic such as coalesce():

    @market_price := IF(market_id = 0, 
                        (SELECT value FROM fiat WHERE id = 6), 
                        (SELECT value FROM fiat WHERE id = 5)
                       ) + 
                       (order_percentage_dynamic/100) * coalesce(@market_price, 0);
    

    Alternatively, you can initialize the values using a join:

    UPDATE market CROSS JOIN
           (select @market_price := 0, @order_price := 0) vars
        SET price =  . . .
    

    My guess is that when you run this on the database, the variables have already been set to non-NULL values.