【问题标题】:Which one is better? case when or if else?哪一个更好?情况何时或如果其他?
【发布时间】:2016-11-29 16:31:05
【问题描述】:

我的情况是这样的:

情况是这样的:

public function get_opportunity($customer_id, $group_id, $action)
{
    $sql = "SELECT COUNT(transaction_id) AS total_transaction 
            FROM `transaction` 
            WHERE 
                CASE 
                    WHEN '$action' = 'view_all' THEN transaction_id IS NOT NULL
                    WHEN '$action' = 'view_group' THEN group_id IN($group_id) 
                    ELSE transaction_created_by = ? 
                END 
            ";

    $result = $this->db->query($sql, array($customer_id))->result_array();

    return ($result[0]['total_transaction']) ? $result[0]['total_transaction'] : 0;
}

如果是这样的话:

public function get_opportunity($customer_id, $group_id, $action)
{
    if($action == "view_all")
        $condition = " transaction_id IS NOT NULL";
    else if($action == 'view_group')
        $condition = " group_id IN($group_id)";
    else
        $condition = " customer_id = ?";

    $sql = "SELECT COUNT(transaction_id) AS total_transaction 
            FROM `transaction` 
            WHERE $condition";

    $result = $this->db->query($sql, array($customer_id))->result_array();

    return ($result[0]['total_transaction']) ? $result[0]['total_transaction'] : 0;
}

我试过了。上述工作的所有类型。但在这里我问,哪个更好?

【问题讨论】:

  • 为什么要在 MySQL 代码中放置基于 PHP 变量的条件?找出您要执行的查询,然后运行正确的查询。不要将其转储到您的数据库中。
  • 另外,请不要内联任意值。尽可能使用prepared statements with placeholder values
  • 我猜这是他的代码的一个功能。只是比较哪个查询更好用。一个组合大声笑
  • 通常按照期望从高到低的顺序:通过关联的array(例如array('view_all' => 'transaction IS NOT NULL', ...))、switch statementif 语句的长链查找。
  • @tadman,我已经尝试了上述两种方法并且它有效。我用mysql数据库

标签: php mysql codeigniter


【解决方案1】:

除了@sagi 提出的问题,实际上第二种方法更好,原因有些不相关。在第一个示例中,您直接在查询字符串内使用变量$action,这可能会打开 SQL 注入的攻击向量,因为它来自方法范围之外并且可能不安全。而在第二个示例中,变量$condition 在方法中受到控制并且可以安全使用。

除此之外,只要性能不是问题,我会考虑可读性。出于这个原因,我什至可以将其拆分为 3 个独立的、明确命名的函数,而不是它们具有非常相似的 SQL。这样一来,发生的事情总是很清楚,并且每个案例都可以独立“增长”,而不是使用一种方法来添加越来越多的案例和 if。

edit:您也可以清楚地命名该函数的功能,例如

  • getAllTransactionCounts()
  • getTransactionCountForCustomers($transactionIds)
  • getTransactionCountForCustomer($customerId)

【讨论】:

  • 那么你认为第二种方式(如果不是的话)没问题吗?
  • @samueltoh 我看不到第二种方法的主要问题,但仍然需要进行一些重构。例如,当 customer_id 和 action 都为 null 时会发生什么?如果 group_id 作为数组而不是逗号分隔列表提供怎么办?这就是为什么我建议将其拆分为 3 个方法(可能是 get_opportunity 调用的私有方法),只使用必要的参数,以使这些案例更清晰、更易于管理。
【解决方案2】:

这不对,第一个代码应该不起作用!在 SQL 中,CASE 是一个表达式,而不是一个语句。您不能对 THEN 部分设置条件,只能设置一个值。 MySQL 将布尔表达式计算为 1\0 ,所以你的情况基本上是这样的:

WHERE CASE... THEN (Cond) -- equals to 1/0 
              THEN (Cond) -- equals to 1/0
              ELSE (Cond) -- -- equals to 1/0 

大多数 RDBMS 都会抛出错误。

你可以这样格式化:

SELECT COUNT(transaction_id) AS total_transaction 
            FROM `transaction` 
            WHERE ('$action' = 'view_all' AND transaction_id IS NOT NULL) OR 
                  ('$action' = 'view_group' THEN group_id IN($group_id)) OR
                  transaction_created_by = ?       

只要你没有性能问题,不要考虑这些事情, 它只会浪费你的时间。选择一个更容易维护的。

【讨论】:

  • 非常感谢。我已经尝试了上述两种方法并且它有效。我用mysql数据库
  • 你如何看待第二种方式(如果有的话)?好用吗?
  • 是的,没关系,就像@dburmann 说的,它会导致SQL-Injection,但总的来说,选择一个更容易维护的。它们都很好,但有时在站点端进行计算和逻辑是首选。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-04
  • 1970-01-01
  • 1970-01-01
  • 2013-04-17
  • 2016-12-24
  • 2012-08-10
  • 2012-07-17
相关资源
最近更新 更多