【问题标题】:Is there a better/alternative way to write a query that accepts an arithmetic operator than using dynamic SQL?有没有比使用动态 SQL 更好/替代的方法来编写接受算术运算符的查询?
【发布时间】:2020-05-25 09:42:52
【问题描述】:

我正在编写一个存储过程,我必须更新一定数量的特定产品(显然我可以增加或减少它)。由于唯一的区别是运算符值( + 或 - )我想在这两种情况下使用相同的过程。我知道这个问题已经在这里得到了回答 - Execute mathematical expression and set the value to variable in SQL ,但这对我没有帮助,因为他们是用 MSSQL 编写的。任何人都知道我怎么能在MYSQL中做到这一点?是不是,如果我用MYSQL写,下面的代码是最好的解决方案?

BEGIN

SET @foundID = -1,@name=name, @company=company;
SET @number=number, @action=plusMinus;
CALL spCheckIfProductExists(@name,@company,@foundID);

IF (@foundID != -1 AND (@action='+' OR @action='-'))
 THEN SET @sql = concat("UPDATE instock SET quantity = quantity",@action , " @number WHERE productid= @foundID");
 PREPARE update_statement FROM @sql;
 EXECUTE update_statement;
 DEALLOCATE PREPARE update_statement;
END IF;
END

这是一个有效的代码,但我知道在编写动态存储过程时连接字符串是一种非常糟糕的做法。任何想法如何改进它?

【问题讨论】:

  • UPDATE table SET value = value + ((condition) * 2 - 1) * delta,其中condition 是您的布尔表达式。如果condition 为TRUE,则将其视为1,您将获得UPDATE table SET value = value + delta。如果condition为FALSE,则视为0,得到UPDATE table SET value = value - delta

标签: mysql sql dynamic


【解决方案1】:

你可以通过@action值改变@number变量的符号

BEGIN
  SET @foundID = -1, @name = name, @company = company;
  SET @action = plusMinus;

  CALL spCheckIfProductExists(@name, @company, @foundID);

  IF (@foundID != -1 AND (@action='+' OR @action='-')) THEN
    IF (@action='-') THEN
      SET @number = number;
    ELSE
      SET @number = -number;
    END IF;
    SET @sql = concat("UPDATE instock SET quantity = quantity + ? WHERE productid = ?");

   PREPARE update_statement FROM @sql;
   EXECUTE update_statement USING @number, @foundID;
   DEALLOCATE PREPARE update_statement;

  END IF;
END;

【讨论】:

    【解决方案2】:

    只要它由whitelist 控制并且不用于填充值上下文(最好以不同方式处理),使用动态生成的SQL 是“可以的”因为生成的 SQL 语句是受控的。

    但是,动态 SQL 是一把大锤,在这里增加了不必要的复杂性。

    在“-”动作情况下,只需将值乘以 -1(阅读:更改符号),然后在占位符或变量上下文中使用它,然后始终使用 + 作为动作: “数量 + x”或“数量 + (-x)”都是有效的。这种特殊情况不适用于“*”等其他运算符。

    SET @adjustment = CASE WHEN @action = '-' THEN -@number ELSE @number END
    
    UPDATE instock SET quantity = quantity + @adjustment
    WHERE productid = @foundID
    

    即使允许其他操作符,这仍然可以通过“CASE @action WHEN ..”来完成,并消除动态 SQL 生成,因为 MySQL 本身会根据操作执行不同的处理,并且操作本身只是指定的是允许的。

     UPDATE instock
     SET quantity = (CASE @action
         WHEN '*' THEN quantity * @number
         WHEN '-' THEN quantity - @number
         WHEN 'e' THEN 2.71828
         ELSE quantity + @number
       END)
     WHERE productid = @foundID
    

    通常仅当查询的形状发生变化时才需要动态构建 SQL 字符串,并且在许多情况下,以针对特定问题的方式处理查询通常会带来更简洁的解决方案。..

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-11-15
      • 2022-11-05
      • 1970-01-01
      • 2020-09-28
      • 1970-01-01
      • 1970-01-01
      • 2023-03-29
      相关资源
      最近更新 更多