动态 Active Record 查询中的 Codeigniter 括号

Posted

技术标签:

【中文标题】动态 Active Record 查询中的 Codeigniter 括号【英文标题】:Codeigniter parentheses in dynamic Active Record query 【发布时间】: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 循环让我失望,我知道如何完成此操作..

【问题讨论】:

【参考方案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 和通配符。

以上是关于动态 Active Record 查询中的 Codeigniter 括号的主要内容,如果未能解决你的问题,请参考以下文章

从 Codeigniter Active Record 中的子查询中选择

如何编写 sa"f"e Active Record 查询

CodeIgniter Active Record 中的 SQL 注释?

Codeigniter Active Record使用多个主键选择多行

Codeigniter Active Record 中的 Concat

Active Record Query Interface 数据查询接口(界面)