【问题标题】:I am using Case for SQL select query and want to calculate price dynamically我正在使用 Case for SQL 选择查询并希望动态计算价格
【发布时间】:2020-08-20 05:31:00
【问题描述】:

我的控制器代码

$nicepay_commission = Configure::read('nicepay_commission');
$paypal_commission = Configure::read('paypal_commission');
 
$getQuery = $this->OrderProduct
    ->find('all', [
        'contain' => [
            'Orders' => ['PaymentMethods'],
            'Products' => ['ProductType']
        ]
    ])
   ->distinct('Products.id')
   ->select([
        'product_name' => 'MAX(Products.product_name)',
        'count' => 'SUM(OrderProduct.qty)', 
        'actual_rate' => 'SUM(OrderProduct.actual_rate)',
        'revenue_based_actual_rate' => '(
            SUM(
                CASE
                WHEN PaymentMethods.payment_gateway = \'nicepay\'
                THEN (OrderProduct.actual_rate-((OrderProduct.actual_rate*"'.$nicepay_commission.'")/100))
                WHEN PaymentMethods.payment_gateway = \'paypal\'
                THEN (OrderProduct.actual_rate-((OrderProduct.actual_rate*"'.$paypal_commission.'")/100))
                ELSE (OrderProduct.actual_rate)
                END
            )
        )'
   ])
   ->where($conditions);

但是发生了一些错误,我找不到如何管理它。

我的错误日志看起来像

2020-08-20 07:56:56 错误:[PDOException] SQLSTATE[42S22]:[Microsoft][ODBC Driver 17 for SQL Server][SQL Server]列名“2”无效。

如果我静态使用这些值,则没有错误

$getQuery = $this->OrderProduct
    ->find('all', [
        'contain' => [
            'Orders' => ['PaymentMethods'],
            'Products' => ['ProductType']
        ]
    ])
    ->distinct('Products.id')
    ->select([
        'product_name' => 'MAX(Products.product_name)',
        'count' => 'SUM(OrderProduct.qty)',
        'actual_rate' => 'SUM(OrderProduct.actual_rate)',
        'revenue_based_actual_rate' => '(
            SUM(
                CASE
                WHEN PaymentMethods.payment_gateway = \'nicepay\'
                THEN (OrderProduct.actual_rate-((OrderProduct.actual_rate*2)/100))
                WHEN PaymentMethods.payment_gateway = \'paypal\'
                THEN (OrderProduct.actual_rate-((OrderProduct.actual_rate*1)/100))
                ELSE (OrderProduct.actual_rate)
                END
            )
        )'
    ])
    ->where($conditions);

【问题讨论】:

    标签: php sql cakephp case query-builder


    【解决方案1】:

    首先,永远不要在可以避免的情况下直接将日期插入 SQL sn-ps,即使您认为它们可能来自安全来源!

    话虽如此,看看生成的 SQL 查询(如果你还没有使用Debug Kit,你应该安装它),你用双引号将值括起来,即生成的 SQL 看起来像:

    OrderProduct.actual_rate * "2"
    

    在 ISO SQL 中意味着 2 将用作标识符。

    删除引号将解决问题,但您仍然将动态数据注入 SQL 字符串,应尽可能避免,因此您应该更进一步并改为绑定值,以减少机会创建 SQL 注入漏洞:

    // ...
    ->select([
        'product_name' => 'MAX(Products.product_name)',
        'count' => 'SUM(OrderProduct.qty)', 
        'actual_rate' => 'SUM(OrderProduct.actual_rate)',
        'revenue_based_actual_rate' => '(
            SUM(
                CASE
                WHEN PaymentMethods.payment_gateway = \'nicepay\'
                THEN (OrderProduct.actual_rate-((OrderProduct.actual_rate * :nicepayCommission)/100))
                WHEN PaymentMethods.payment_gateway = \'paypal\'
                THEN (OrderProduct.actual_rate-((OrderProduct.actual_rate * :paypalCommission)/100))
                ELSE (OrderProduct.actual_rate)
                END
            )
        )'
    ])
    ->bind(':nicepayCommission', $nicepay_commission, 'integer')
    ->bind(':paypalCommission', $paypal_commission, 'integer')
    // ...
    

    另见

    【讨论】:

    • 我正在使用您所写的绑定,但日志中仍然存在错误-“无效的参数号:绑定变量的数量与标记的数量不匹配”。怎么解决?
    • @PriyankaHazra 这不应该发生在我展示的示例中,它正好有 2 个占位符并绑定到它们,所以应该没有不匹配。确保您没有拼写错误,并调试您的查询以找出问题所在(debug($query),检查sqlparams 键)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-28
    • 1970-01-01
    • 2013-10-29
    • 2012-01-17
    • 2020-12-09
    • 2021-11-01
    相关资源
    最近更新 更多