【问题标题】:Codeigniter parentheses in dynamic Active Record query动态 Active Record 查询中的 Codeigniter 括号
【发布时间】:2011-09-27 00:36:35
【问题描述】:

我正在使用 ActiveRecord 生成如下查询

SELECT * FROM (`foods`) WHERE `type` = 'fruits' AND 
       `tags` LIKE '%green%' OR `tags` LIKE '%blue%' OR `tags` LIKE '%red%'

tags 的数量和值未知。数组是动态创建的。下面我添加了一个可能的数组。

$tags = array (                 
        '0'     => 'green'.
        '1'     => 'blue',
        '2'     => 'red'
);  

有一个标签数组,我使用以下循环来创建我在顶部发布的查询。

$this->db->where('type', $type); //var type is retrieved from input value

foreach($tags as $tag):         
     $this->db->or_like('tags', $tag);
endforeach; 

问题:我需要在LIKE 子句周围添加括号,如下所示:

SELECT * FROM (`foods`) WHERE `type` = 'fruits' AND 
      (`tags` LIKE '%green%' OR `tags` LIKE '%blue%' OR `tags` LIKE '%red%')

如果括号内的内容是静态的,但 foreach 循环让我失望,我知道如何完成此操作..

【问题讨论】:

    标签: mysql arrays codeigniter activerecord


    【解决方案1】:

    来自 CI wiki:

    codeignighter ActiveRecord 功能 允许您创建 SQL 查询 比较简单和 独立于数据库,但是有 没有具体支持包括 SQL 查询中的括号。

    例如,当您希望 where 语句类似于以下内容时:

    WHERE (field1 = value || field2 = value) AND (field3 = value2 || field4 = value2) 
    

    这可以通过向 CI->db->where() 函数提供一个字符串来解决,在这种情况下,您需要专门转义您的值。

    请看下面的例子:

    $value=$this->db->escape($value);
    $value2=$this->db->escape($value2);
    $this->db->from('sometable');
    $this->db->where("($field = $value || $field2 = $value)");
    $this->db->where("($field3 = $value2 || $field4 = $value2)");
    $this->db->get(); 
    

    类似的解决方法可用于 LIKE 子句:

    $this->db->where("($field LIKE '%$value%' || $field2 LIKE '%$value%')");
    $this->db->where("($field3 LIKE '%$value2%' || $field4 LIKE '%$value2%')"); 
    

    【讨论】:

    • 感谢@The Silencer,这是很好的信息。使用您的示例,我像这样编辑了循环,foreach($tags as $tag): $this->db->where("($field LIKE '%$tag%')"); endforeach; 这给了我这种查询SELECT * FROM ('foods') WHERE 'type' = 'fruits' AND (tags LIKE '%green%') AND (tags LIKE '%red%') AND (tags LIKE '%blue%') 每个LIKE 子句都可以放在单独的括号中吗?我不能像您的示例那样将所有子句放在一个查询中,因为我的子句是动态创建的。
    • 对任何试图实现这一点的人请注意:对于转义LIKE 子句,codeigniter 使用$this->db->escape_like_str($value),否则它会在通配符内添加单引号。
    • 谢谢你 - 我再也没有使用 CI 3 小时后,这只是让我觉得!
    • 我使用了来自 CI、Yii、Zend、AdoDB 等多个框架的 DB 抽象。Laravel 在简单性和可读性方面确实胜过它们。如果您还没有这样做,请检查一下!并且如果你不想使用整个 laravel 框架,你不必使用,只需使用 DB 包。
    • 谢谢,这正是我要找的。它就像一个魅力,干杯!!!
    【解决方案2】:

    在 CI 3.0-dev 中,您可以在查询中添加组:

    $this->db->select('id, title')
    ->group_start()
    ->or_like([ 'title' => $s, 'id' => $s ])
    ->group_end()                
    ->where([ 'b_del' => 0 ]);
    

    生产:

    SELECT `id`, `title`, `venda1`
    FROM `itens`
    WHERE   
    (
    `title` LIKE '%a%' ESCAPE '!'
    OR  `id` LIKE '%a%' ESCAPE '!'
     )
    AND `b_del` =0 
    

    【讨论】:

      【解决方案3】:

      应用多个 where or_where 子句时保存查询的最佳功能之一。

      $this->db->group_start();
      $this->db->where();
      $this->db->or_where();
      $this->db->group_end();
      

      快乐编码。 :)

      【讨论】:

      • 出于某种原因,CI 在我的第一个引号中添加了一个额外的引号,当我包含括号时:类似于“age > 5 and state ='MN'”。然后我需要添加一个额外的位置(使用 AND)。所以,需要括号。这解决了我的问题!
      【解决方案4】:

      脱离 The Silencer 的解决方案,我编写了一个小函数来帮助构建类似的条件

      function make_like_conditions (array $fields, $query) {
          $likes = array();
          foreach ($fields as $field) {
              $likes[] = "$field LIKE '%$query%'";
          }
          return '('.implode(' || ', $likes).')';
      }
      

      你会这样使用它:

      $search_fields = array(
          'field_1',
          'field_2',
          'field_3',
      );
      $query = "banana"
      $like_conditions = make_like_conditions($search_fields, $query);
      $this->db->from('sometable')
          ->where('field_0', 'foo')
          ->where($like_conditions)
          ->get()
      

      【讨论】:

        【解决方案5】:

        只需添加我成功的解决方案:

        $this->db->where("(table.field = $variable OR table.field IS NULL)");
        

        【讨论】:

          【解决方案6】:

          使用 codeigniter 3

          $this->db->select('*');
              $this->db->from($this->MasterMember);
              $this->db->group_start();
              $this->db->where($this->IDCardStatus, '1');
              $this->db->or_where($this->IDCardStatus, '2');
              $this->db->group_end();
          
              if ($searchKey1 != null) {
                  $this->db->group_start();
                  $this->db->like($this->MemberID, $searchKey1);
                  $this->db->or_like($this->FirstName, $searchKey2);
                  $this->db->or_like($this->LastName, $searchKey3);
                  $this->db->group_end();
              }
          
              $this->db->limit($limit, $offset);
          
          
              $data = $this->db->get();
          

          这是我的原生查询

          SELECT
              * 
          FROM
              `Member` 
          WHERE ( `Member`.`IDCardStatus` = '1' OR `Member`.`IDCardStatus` = '2' ) 
          AND ( `Member`.`MemberID` LIKE '%some_key%' ESCAPE '!' OR `Member`.`FirstName` LIKE '%some_key%' ESCAPE '!' OR `Member`.`LastName` LIKE '%some_key%' ESCAPE '!' ) 
              LIMIT 10
          

          【讨论】:

            【解决方案7】:

            codeigniter 4 的更新:

            $builder->select('*')->from('my_table')
                    ->groupStart()
                        ->where('a', 'a')
                        ->orGroupStart()
                                ->where('b', 'b')
                                ->where('c', 'c')
                        ->groupEnd()
                ->groupEnd()
                ->where('d', 'd')
            ->get();
            
            // Generates:
            // SELECT * FROM (`my_table`) WHERE ( `a` = 'a' OR ( `b` = 'b' AND `c` = 'c' ) ) AND `d` = 'd'
            

            来自官方文档:https://codeigniter.com/user_guide/database/query_builder.html#query-grouping

            【讨论】:

              【解决方案8】:
              $likes = array (                 
                  '0'     => 'green'.
                  '1'     => 'blue',
                  '2'     => 'red'
              );  
              $where_like = "("; 
              $or_counter = 1;
              foreach($likes as $like_key => $like_val):
                  $or_content = ($or_counter > 1) ?'OR': '';
                  $newlikeval = $this->db->escape_like_str($like_val);
                  $where_like .= $or_content." `$like_key` LIKE  '%$newlikeval%' ";
                  $or_counter++;
              endforeach;
              $where_like .= ")";
              $this->db->where($where_like);
              

              【讨论】:

                【解决方案9】:

                您不能在 ActiveRecord 中添加括号,但也许 WHERE IN 是您要查找的内容?

                $names = array('Frank', 'Todd', 'James');
                $this->db->where_in('username', $names);
                // Produces: WHERE username IN ('Frank', 'Todd', 'James')
                

                【讨论】:

                • 这根本不是一回事。很可能它是一种搜索功能,需要 LIKE 和通配符。
                猜你喜欢
                • 2014-06-26
                • 1970-01-01
                • 2016-03-15
                • 2012-04-17
                • 2013-02-22
                • 2013-01-09
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多